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 /** 365 * TJJ - quick hack, just do something visually jarring to test path 366 */ 367 368 /** 369 * Computes a Rayleigh scattering corrected 2D grid for visible range data. 370 * 371 * @param visibleDataGrid 2D grid of remote sensing data in the visible range 372 * (assuming it represents top-of-atmosphere radiance or reflectance). 373 * @param satelliteZenithGrid 2D grid of satellite zenith angles (in degrees). 374 * @param solarZenithGrid 2D grid of solar zenith angles (in degrees). 375 * @param satelliteAzimuthGrid 2D grid of satellite azimuth angles (in degrees). 376 * @param solarAzimuthGrid 2D grid of solar azimuth angles (in degrees). 377 * @param wavelengthVisible Wavelength of the visible band (in micrometers). 378 * @param atmosphericPressure Atmospheric pressure at the surface (in hPa). 379 * @return A 2D grid representing the Rayleigh scattering corrected data. 380 * @throws IllegalArgumentException if input grid dimensions are inconsistent. 381 */ 382 383 public static FieldImpl correctRayleighVisible(FieldImpl visibleField, 384 FieldImpl satelliteZenithField, 385 FieldImpl solarZenithField, 386 FieldImpl satelliteAzimuthField, 387 FieldImpl solarAzimuthField, 388 double wavelengthVisible, 389 double atmosphericPressure) 390 throws VisADException, RemoteException { 391 392 double[][] visibleDataGrid = visibleField.getValues(); 393 double[][] satelliteZenithGrid = satelliteZenithField.getValues(); 394 double[][] solarZenithGrid = solarZenithField.getValues(); 395 double[][] satelliteAzimuthGrid = satelliteAzimuthField.getValues(); 396 double[][] solarAzimuthGrid = solarAzimuthField.getValues(); 397 398 int rows = visibleDataGrid.length; 399 int cols = visibleDataGrid[0].length; 400 401 // float[][] correctedDataGrid = new float[rows][cols]; 402 403 for (int i = 0; i < rows; i++) { 404 for (int j = 0; j < cols; j++) { 405 float thetaV = (float) Math.toRadians(satelliteZenithGrid[i][j]); 406 float thetaS = (float) Math.toRadians(solarZenithGrid[i][j]); 407 float phiV = (float) Math.toRadians(satelliteAzimuthGrid[i][j]); 408 float phiS = (float) Math.toRadians(solarAzimuthGrid[i][j]); 409 410 double rhoRayleigh = calculateRayleighReflectance(wavelengthVisible, thetaS, thetaV, phiS, phiV, atmosphericPressure); 411 visibleDataGrid[i][j] = (float) (visibleDataGrid[i][j] - rhoRayleigh); 412 } 413 } 414 visibleField.setSamples(visibleDataGrid); 415 416 logger.info("3141 - made it out"); 417 return visibleField; 418 } 419 420 // Calculate Rayleigh reflectance - McIDAS Inquiry #3055-3141 421 private static double calculateRayleighReflectance( 422 double wavelength, double solarZenithRad, double satelliteZenithRad, 423 double solarAzimuthRad, double satelliteAzimuthRad, double pressureHPa) { 424 425 double tau_ro = (0.008569 / Math.pow(wavelength, 4)) 426 * (1 + (0.0113 / Math.pow(wavelength, 2)) + (0.00013 / Math.pow(wavelength, 4))); 427 428 // \tau_{ro} = \frac{0.008569}{\lambda^4} \cdot (1 + \frac{0.0113}{\lambda^2} + \frac{0.00013}{\lambda^4}) 429 430 double pressure_rat = pressureHPa / 1013.25; 431 // P = \frac{pHPa}{atmP} 432 433 double tau = pressure_rat * tau_ro; // this is the only thing matters next 434 // \tau = P \cdot \tau_{ro} 435 436 double scattering_angle_cos = Math.cos(solarZenithRad) * Math.cos(satelliteZenithRad) 437 + Math.sin(solarZenithRad) * Math.sin(satelliteZenithRad) 438 * Math.cos(satelliteAzimuthRad - solarAzimuthRad); 439 440 // \cos (\Theta) = \cos (\theta_{sun})\cos (\theta_{sat}) + \sin (\theta_{sun})\sin (\theta_{sat}) \cdot \cos(\phi_{sat} - \phi_{sun}) 441 442 double P_big_theta = 0.75 * (1 + Math.pow(scattering_angle_cos, 2)); // another important value 443 // P(\Theta) = 0.75 * (1 + (\cos(\Theta))^2) 444 445 double mu_1 = Math.cos(solarZenithRad); 446 double mu_2 = Math.cos(solarZenithRad); 447 448 return tau * P_big_theta * (1 / (4 * mu_1 * mu_2)); 449 // \tau \cdot P(\Theta) \cdot (\frac{1}{4 \cdot \mu_1 \cdot \mu_2}) 450 } 451 452 private void applyRayleighCorrection() { 453 float[][] newRedTbl = getZeroOutArray(redTable); 454 float[][] newGrnTbl = getZeroOutArray(grnTable); 455 float[][] newBluTbl = getZeroOutArray(bluTable); 456 457 for (int k = 0; k < redTable[0].length; k++) { 458 newRedTbl[0][k] = (float) Math.pow(redTable[0][k], 0.2); 459 newGrnTbl[1][k] = (float) Math.pow(grnTable[1][k], 0.2); 460 newBluTbl[2][k] = (float) Math.pow(bluTable[2][k], 0.2); 461 } 462 try { 463 displayMaster.setDisplayInactive(); 464 ((BaseColorControl) redMap.getControl()).setTable(newRedTbl); 465 ((BaseColorControl) grnMap.getControl()).setTable(newGrnTbl); 466 ((BaseColorControl) bluMap.getControl()).setTable(newBluTbl); 467 displayMaster.setDisplayActive(); 468 } catch (Exception e) { 469 LogUtil.logException("setDisplayInactive", e); 470 } 471 } 472 473 private void updateGamma(double gamma) { 474 setGamma(gamma); 475 setRedGamma(gamma); 476 setGrnGamma(gamma); 477 setBluGamma(gamma); 478 redGammaTxtFld.setText(Float.toString((float)gamma)); 479 grnGammaTxtFld.setText(Float.toString((float)gamma)); 480 bluGammaTxtFld.setText(Float.toString((float)gamma)); 481 482 float[][] newRedTbl = getZeroOutArray(redTable); 483 float[][] newGrnTbl = getZeroOutArray(grnTable); 484 float[][] newBluTbl = getZeroOutArray(bluTable); 485 486 for (int k=0; k<redTable[0].length; k++) { 487 newRedTbl[0][k] = (float) Math.pow(redTable[0][k], gamma); 488 newGrnTbl[1][k] = (float) Math.pow(grnTable[1][k], gamma); 489 newBluTbl[2][k] = (float) Math.pow(bluTable[2][k], gamma); 490 } 491 try { 492 displayMaster.setDisplayInactive(); 493 ((BaseColorControl)redMap.getControl()).setTable(newRedTbl); 494 ((BaseColorControl)grnMap.getControl()).setTable(newGrnTbl); 495 ((BaseColorControl)bluMap.getControl()).setTable(newBluTbl); 496 displayMaster.setDisplayActive(); 497 } catch (Exception ex) { 498 LogUtil.logException("setDisplayInactive", ex); 499 } 500 } 501 502 private void updateRedGamma(double gamma) { 503 setRedGamma(gamma); 504 505 float[][] newRedTbl = getZeroOutArray(redTable); 506 507 for (int k=0; k<redTable[0].length; k++) { 508 newRedTbl[0][k] = (float) Math.pow(redTable[0][k], gamma); 509 } 510 511 try { 512 displayMaster.setDisplayInactive(); 513 ((BaseColorControl)redMap.getControl()).setTable(newRedTbl); 514 displayMaster.setDisplayActive(); 515 } catch (Exception ex) { 516 LogUtil.logException("setDisplayInactive", ex); 517 } 518 } 519 520 private void updateGrnGamma(double gamma) { 521 setGrnGamma(gamma); 522 523 float[][] newGrnTbl = getZeroOutArray(grnTable); 524 for (int k=0; k<grnTable[0].length; k++) { 525 newGrnTbl[1][k] = (float) Math.pow(grnTable[1][k], gamma); 526 } 527 528 try { 529 displayMaster.setDisplayInactive(); 530 ((BaseColorControl)grnMap.getControl()).setTable(newGrnTbl); 531 displayMaster.setDisplayActive(); 532 } catch (Exception ex) { 533 LogUtil.logException("setDisplayInactive", ex); 534 } 535 } 536 537 private void updateBluGamma(double gamma) { 538 setBluGamma(gamma); 539 540 float[][] newBluTbl = getZeroOutArray(bluTable); 541 for (int k=0; k<bluTable[0].length; k++) { 542 newBluTbl[2][k] = (float) Math.pow(bluTable[2][k], gamma); 543 } 544 545 try { 546 displayMaster.setDisplayInactive(); 547 ((BaseColorControl)bluMap.getControl()).setTable(newBluTbl); 548 displayMaster.setDisplayActive(); 549 } catch (Exception ex) { 550 LogUtil.logException("setDisplayInactive", ex); 551 } 552 } 553 554 public float[][] getZeroOutArray(float[][] array) { 555 float[][] newArray = new float[array.length][array[0].length]; 556 for (int i=0; i<newArray.length; i++) { 557 for (int j=0; j<newArray[0].length; j++) { 558 newArray[i][j] = 0.0f; 559 } 560 } 561 return newArray; 562 } 563 564 protected ColorTable getInitialColorTable() { 565 return getDisplayConventions().getParamColorTable("image"); 566 } 567 568 void setAllFields(String txtl1, String txtl2) { 569 Double l1 = Double.valueOf(txtl1.trim()); 570 Double l2 = Double.valueOf(txtl2.trim()); 571 bluRange[0] = l1; 572 bluRange[1] = l2; 573 redRange[0] = l1; 574 redRange[1] = l2; 575 grnRange[0] = l1; 576 grnRange[1] = l2; 577 updateRedRange(redRange[0], redRange[1]); 578 updateBluRange(redRange[0], redRange[1]); 579 updateGrnRange(redRange[0], redRange[1]); 580 581 redLowTxtFld.setText(txtl1); 582 grnLowTxtFld.setText(txtl1); 583 bluLowTxtFld.setText(txtl1); 584 585 redHighTxtFld.setText(txtl2); 586 bluHighTxtFld.setText(txtl2); 587 grnHighTxtFld.setText(txtl2); 588 } 589 590 public Container doMakeContents() { 591 592 JButton allGammaButton = new JButton("Apply to All Gamma Fields"); 593 allGammaButton.addActionListener(e -> { 594 String tmp = gammaTxtFld.getText().trim(); 595 updateGamma(Double.valueOf(tmp)); 596 }); 597 598 gammaTxtFld.addActionListener(e -> { 599 String tmp = gammaTxtFld.getText().trim(); 600 updateGamma(Double.valueOf(tmp)); 601 }); 602 603 // McIDAS Inquiry #3193-3141 604 redLowTxtFld.addActionListener(e -> { 605 if (matchFieldsCbox.isSelected()) 606 setAllFields(redLowTxtFld.getText(),redHighTxtFld.getText()); 607 608 Double l1 = Double.valueOf(redLowTxtFld.getText().trim()); 609 Double l2 = Double.valueOf(redHighTxtFld.getText().trim()); 610 redRange[0] = l1; 611 redRange[1] = l2; 612 updateRedRange(redRange[0], redRange[1]); 613 614 }); 615 616 redHighTxtFld.addActionListener(e -> { 617 if (matchFieldsCbox.isSelected()) 618 setAllFields(redLowTxtFld.getText(),redHighTxtFld.getText()); 619 620 Double l1 = Double.valueOf(redLowTxtFld.getText().trim()); 621 Double l2 = Double.valueOf(redHighTxtFld.getText().trim()); 622 redRange[0] = l1; 623 redRange[1] = l2; 624 updateRedRange(redRange[0], redRange[1]); 625 }); 626 627 redGammaTxtFld.addActionListener(e -> { 628 String tmp = redGammaTxtFld.getText().trim(); 629 updateRedGamma(Double.valueOf(tmp)); 630 631 if (matchFieldsCbox.isSelected()) { 632 grnGammaTxtFld.setText(tmp); 633 bluGammaTxtFld.setText(tmp); 634 updateBluGamma(Double.valueOf(tmp)); 635 updateGrnGamma(Double.valueOf(tmp)); 636 } 637 }); 638 639 JButton redReset = new JButton("Reset"); 640 redReset.addActionListener(e -> { 641 updateRedRange(initRedRange[0], initRedRange[1]); 642 redRange[0] = initRedRange[0]; 643 redRange[1] = initRedRange[1]; 644 redLowTxtFld.setText(Float.toString((float)redRange[0])); 645 redHighTxtFld.setText(Float.toString((float)redRange[1])); 646 updateRedGamma(1.0); 647 redGammaTxtFld.setText("1.0"); 648 }); 649 650 grnLowTxtFld.addActionListener(e -> { 651 if (matchFieldsCbox.isSelected()) 652 setAllFields(grnLowTxtFld.getText(),grnHighTxtFld.getText()); 653 654 Double l1 = Double.valueOf(grnLowTxtFld.getText().trim()); 655 Double l2 = Double.valueOf(grnHighTxtFld.getText().trim()); 656 grnRange[0] = l1; 657 grnRange[1] = l2; 658 updateGrnRange(grnRange[0], grnRange[1]); 659 }); 660 661 grnHighTxtFld.addActionListener(e -> { 662 if (matchFieldsCbox.isSelected()) 663 setAllFields(grnLowTxtFld.getText(),grnHighTxtFld.getText()); 664 665 Double l1 = Double.valueOf(grnLowTxtFld.getText().trim()); 666 Double l2 = Double.valueOf(grnHighTxtFld.getText().trim()); 667 grnRange[0] = l1; 668 grnRange[1] = l2; 669 updateGrnRange(grnRange[0], grnRange[1]); 670 }); 671 672 grnGammaTxtFld.addActionListener(e -> { 673 String tmp = grnGammaTxtFld.getText().trim(); 674 updateGrnGamma(Double.valueOf(tmp)); 675 676 if (matchFieldsCbox.isSelected()) { 677 redGammaTxtFld.setText(tmp); 678 bluGammaTxtFld.setText(tmp); 679 updateRedGamma(Double.valueOf(tmp)); 680 updateGrnGamma(Double.valueOf(tmp)); 681 } 682 }); 683 684 JButton grnReset = new JButton("Reset"); 685 grnReset.addActionListener(e -> { 686 updateGrnRange(initGrnRange[0], initGrnRange[1]); 687 grnRange[0] = initGrnRange[0]; 688 grnRange[1] = initGrnRange[1]; 689 grnLowTxtFld.setText(Float.toString((float)grnRange[0])); 690 grnHighTxtFld.setText(Float.toString((float)grnRange[1])); 691 updateGrnGamma(1.0); 692 grnGammaTxtFld.setText("1.0"); 693 }); 694 695 bluLowTxtFld.addActionListener(e -> { 696 if (matchFieldsCbox.isSelected()) 697 setAllFields(bluLowTxtFld.getText(),bluHighTxtFld.getText()); 698 699 Double l1 = Double.valueOf(bluLowTxtFld.getText().trim()); 700 Double l2 = Double.valueOf(bluHighTxtFld.getText().trim()); 701 bluRange[0] = l1; 702 bluRange[1] = l2; 703 updateBluRange(bluRange[0], bluRange[1]); 704 }); 705 706 bluHighTxtFld.addActionListener(e -> { 707 if (matchFieldsCbox.isSelected()) 708 setAllFields(bluLowTxtFld.getText(),bluHighTxtFld.getText()); 709 710 Double l1 = Double.valueOf(bluLowTxtFld.getText().trim()); 711 Double l2 = Double.valueOf(bluHighTxtFld.getText().trim()); 712 bluRange[0] = l1; 713 bluRange[1] = l2; 714 updateBluRange(bluRange[0], bluRange[1]); 715 }); 716 717 bluGammaTxtFld.addActionListener(e -> { 718 String tmp = bluGammaTxtFld.getText().trim(); 719 updateBluGamma(Double.valueOf(tmp)); 720 721 if (matchFieldsCbox.isSelected()) { 722 grnGammaTxtFld.setText(tmp); 723 redGammaTxtFld.setText(tmp); 724 updateGrnGamma(Double.valueOf(tmp)); 725 updateRedGamma(Double.valueOf(tmp)); 726 } 727 }); 728 729 JButton bluReset = new JButton("Reset"); 730 bluReset.addActionListener(e -> { 731 updateBluRange(initBluRange[0], initBluRange[1]); 732 bluRange[0] = initBluRange[0]; 733 bluRange[1] = initBluRange[1]; 734 bluLowTxtFld.setText(Float.toString((float)bluRange[0])); 735 bluHighTxtFld.setText(Float.toString((float)bluRange[1])); 736 updateBluGamma(1.0); 737 bluGammaTxtFld.setText("1.0"); 738 }); 739 740 JButton applyButton = new JButton("Apply"); 741 applyButton.addActionListener(e -> { 742 String redLow = redLowTxtFld.getText().trim(); 743 String redHigh = redHighTxtFld.getText().trim(); 744 updateRedRange(Double.valueOf(redLow), Double.valueOf(redHigh)); 745 String grnLow = grnLowTxtFld.getText().trim(); 746 String grnHigh = grnHighTxtFld.getText().trim(); 747 updateGrnRange(Double.valueOf(grnLow), Double.valueOf(grnHigh)); 748 String bluLow = bluLowTxtFld.getText().trim(); 749 String bluHigh = bluHighTxtFld.getText().trim(); 750 updateBluRange(Double.valueOf(bluLow), Double.valueOf(bluHigh)); 751 752 String tmp1 = redGammaTxtFld.getText().trim(); 753 updateRedGamma(Double.valueOf(tmp1)); 754 String tmp2 = grnGammaTxtFld.getText().trim(); 755 updateGrnGamma(Double.valueOf(tmp2)); 756 String tmp3 = bluGammaTxtFld.getText().trim(); 757 updateBluGamma(Double.valueOf(tmp3)); 758 }); 759 760 // McIDAS Inquiry #3193-3141 761 matchFieldsCbox = new JCheckBox(); 762 matchFieldsCbox.setToolTipText("When enabled, changing a setting for one color changes the setting for all colors."); 763 JPanel topPanel = new JPanel(new MigLayout()); 764 topPanel.add(new JLabel("Match fields: ")); 765 topPanel.add(matchFieldsCbox, "wrap"); 766 topPanel.add(new JLabel("Red Range: ")); 767 topPanel.add(redLowTxtFld); 768 topPanel.add(redHighTxtFld); 769 topPanel.add(new JLabel("Red Gamma: ")); 770 topPanel.add(redGammaTxtFld); 771 topPanel.add(redReset, "wrap"); 772 773 topPanel.add(new JLabel("Green Range: ")); 774 topPanel.add(grnLowTxtFld); 775 topPanel.add(grnHighTxtFld); 776 topPanel.add(new JLabel("Green Gamma: ")); 777 topPanel.add(grnGammaTxtFld); 778 topPanel.add(grnReset, "wrap"); 779 780 topPanel.add(new JLabel("Blue Range: ")); 781 topPanel.add(bluLowTxtFld); 782 topPanel.add(bluHighTxtFld); 783 topPanel.add(new JLabel("Blue Gamma: ")); 784 topPanel.add(bluGammaTxtFld); 785 topPanel.add(bluReset, "wrap"); 786 787 topPanel.add(Box.createHorizontalStrut(2), "span 5"); 788 topPanel.add(applyButton, "wrap"); 789 790 JPanel bottomPanel = new JPanel(new MigLayout()); 791 bottomPanel.add(new JLabel("Common Gamma: ")); 792 bottomPanel.add(gammaTxtFld); 793 bottomPanel.add(allGammaButton, "wrap"); 794 bottomPanel.add(new JLabel("Vertical Position: ")); 795 bottomPanel.add(doMakeZPositionSlider()); 796 797 JPanel mainPanel = new JPanel(new FlowLayout(FlowLayout.LEFT)); 798 mainPanel.add(topPanel); 799 mainPanel.add(bottomPanel); 800 801 return mainPanel; 802 } 803 804 private class ColorMapListener implements ScalarMapListener { 805 ScalarMap clrMap; 806 807 double[] range = null; 808 double[] initRange = null; 809 810 JTextField lowTxtFld; 811 JTextField highTxtFld; 812 813 ColorMapListener(ScalarMap clrMap, double[] initRange, double[] range, JTextField lowTxtFld, JTextField highTxtFld) { 814 this.clrMap = clrMap; 815 this.lowTxtFld = lowTxtFld; 816 this.highTxtFld = highTxtFld; 817 this.range = range; 818 this.initRange = initRange; 819 } 820 821 public void controlChanged(ScalarMapControlEvent event) throws RemoteException, VisADException { 822 } 823 824 @Override 825 public void mapChanged(ScalarMapEvent event) throws RemoteException, VisADException { 826 if (event.getId() == ScalarMapEvent.AUTO_SCALE) { 827 double[] rng = clrMap.getRange(); 828 boolean shouldRemove = false; 829 //Ghansham: decide whether it is first time. The cleaner way 830 if (!Double.isNaN(rng[0]) && !Double.isNaN(rng[1]) && Double.isNaN(initRange[0]) && Double.isNaN(initRange[1])) { 831 shouldRemove = true; 832 } 833 range[0] = rng[0]; 834 range[1] = rng[1]; 835 initRange[0] = rng[0]; 836 initRange[1] = rng[1]; 837 lowTxtFld.setText(Float.toString((float)rng[0])); 838 highTxtFld.setText(Float.toString((float)rng[1])); 839 //Ghansham:If its first time remove the scalarmaplistener and setRange manually to disable autscaling of the scalarmap 840 if (shouldRemove) { 841 clrMap.removeScalarMapListener(this); 842 //-Lock out auto-scaling 843 clrMap.disableAutoScale(); 844 } 845 } else if (event.getId() == ScalarMapEvent.MANUAL) { 846 double[] rng = clrMap.getRange(); 847 range[0] = rng[0]; 848 range[1] = rng[1]; 849 } 850 } 851 } 852}