001 /* 002 * $Id: AddeImageParameterDataSource.java,v 1.30 2012/04/26 17:11:50 tomw Exp $ 003 * 004 * This file is part of McIDAS-V 005 * 006 * Copyright 2007-2012 007 * Space Science and Engineering Center (SSEC) 008 * University of Wisconsin - Madison 009 * 1225 W. Dayton Street, Madison, WI 53706, USA 010 * https://www.ssec.wisc.edu/mcidas 011 * 012 * All Rights Reserved 013 * 014 * McIDAS-V is built on Unidata's IDV and SSEC's VisAD libraries, and 015 * some McIDAS-V source code is based on IDV and VisAD source code. 016 * 017 * McIDAS-V is free software; you can redistribute it and/or modify 018 * it under the terms of the GNU Lesser Public License as published by 019 * the Free Software Foundation; either version 3 of the License, or 020 * (at your option) any later version. 021 * 022 * McIDAS-V is distributed in the hope that it will be useful, 023 * but WITHOUT ANY WARRANTY; without even the implied warranty of 024 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 025 * GNU Lesser Public License for more details. 026 * 027 * You should have received a copy of the GNU Lesser Public License 028 * along with this program. If not, see http://www.gnu.org/licenses. 029 */ 030 031 package edu.wisc.ssec.mcidasv.data.adde; 032 033 import java.awt.Component; 034 import java.awt.Container; 035 import java.awt.Dimension; 036 import java.awt.event.ActionEvent; 037 import java.awt.event.ActionListener; 038 import java.io.File; 039 import java.io.RandomAccessFile; 040 import java.rmi.RemoteException; 041 import java.text.SimpleDateFormat; 042 import java.util.ArrayList; 043 import java.util.Arrays; 044 import java.util.Comparator; 045 import java.util.Enumeration; 046 import java.util.Hashtable; 047 import java.util.Iterator; 048 import java.util.List; 049 import java.util.StringTokenizer; 050 import java.util.TimeZone; 051 import java.util.TreeMap; 052 053 import javax.swing.BoxLayout; 054 import javax.swing.JCheckBox; 055 import javax.swing.JComponent; 056 import javax.swing.JLabel; 057 import javax.swing.JPanel; 058 import javax.swing.JScrollPane; 059 import javax.swing.JTabbedPane; 060 061 import org.slf4j.Logger; 062 import org.slf4j.LoggerFactory; 063 064 import edu.wisc.ssec.mcidas.AREAnav; 065 import edu.wisc.ssec.mcidas.AreaDirectory; 066 import edu.wisc.ssec.mcidas.AreaDirectoryList; 067 import edu.wisc.ssec.mcidas.AreaFile; 068 import edu.wisc.ssec.mcidas.adde.AddeImageURL; 069 import edu.wisc.ssec.mcidas.adde.AddeTextReader; 070 071 import visad.Data; 072 import visad.DateTime; 073 import visad.FlatField; 074 import visad.FunctionType; 075 import visad.MathType; 076 import visad.RealType; 077 import visad.Set; 078 import visad.VisADException; 079 import visad.data.DataRange; 080 import visad.data.mcidas.AREACoordinateSystem; 081 import visad.data.mcidas.AreaAdapter; 082 import visad.georef.MapProjection; 083 import visad.meteorology.ImageSequence; 084 import visad.meteorology.ImageSequenceImpl; 085 import visad.meteorology.ImageSequenceManager; 086 import visad.meteorology.SingleBandedImage; 087 import visad.util.ThreadManager; 088 089 import ucar.nc2.iosp.mcidas.McIDASAreaProjection; 090 import ucar.unidata.data.BadDataException; 091 import ucar.unidata.data.CompositeDataChoice; 092 import ucar.unidata.data.DataCategory; 093 import ucar.unidata.data.DataChoice; 094 import ucar.unidata.data.DataSelection; 095 import ucar.unidata.data.DataSelectionComponent; 096 import ucar.unidata.data.DataSourceDescriptor; 097 import ucar.unidata.data.DirectDataChoice; 098 import ucar.unidata.data.GeoLocationInfo; 099 import ucar.unidata.data.GeoSelection; 100 import ucar.unidata.data.imagery.AddeImageDataSource; 101 import ucar.unidata.data.imagery.AddeImageDescriptor; 102 import ucar.unidata.data.imagery.AddeImageInfo; 103 import ucar.unidata.data.imagery.BandInfo; 104 import ucar.unidata.data.imagery.ImageDataset; 105 import ucar.unidata.geoloc.LatLonPoint; 106 import ucar.unidata.geoloc.ProjectionImpl; 107 import ucar.unidata.idv.DisplayControl; 108 import ucar.unidata.util.GuiUtils; 109 import ucar.unidata.util.IOUtil; 110 import ucar.unidata.util.LogUtil; 111 import ucar.unidata.util.PollingInfo; 112 import ucar.unidata.util.StringUtil; 113 import ucar.unidata.util.ThreeDSize; 114 import ucar.unidata.util.TwoFacedObject; 115 import ucar.visad.Util; 116 import ucar.visad.data.AreaImageFlatField; 117 118 import edu.wisc.ssec.mcidasv.data.GeoLatLonSelection; 119 import edu.wisc.ssec.mcidasv.data.GeoPreviewSelection; 120 121 /** 122 * Abstract DataSource class for images files. 123 */ 124 public class AddeImageParameterDataSource extends AddeImageDataSource { 125 126 private static final Logger logger = LoggerFactory.getLogger(AddeImageParameterDataSource.class); 127 128 /** 129 * Public keys for server, group, dataset, user, project. 130 */ 131 public final static String SIZE_KEY = "size"; 132 public final static String PLACE_KEY = "place"; 133 public final static String LATLON_KEY = "latlon"; 134 public final static String LINELE_KEY = "linele"; 135 public final static String MAG_KEY = "mag"; 136 public final static String BAND_KEY = "band"; 137 public final static String BANDINFO_KEY = "bandinfo"; 138 public final static String UNIT_KEY = "unit"; 139 public final static String PREVIEW_KEY = "preview"; 140 public final static String SPAC_KEY = "spac"; 141 public final static String NAV_KEY = "nav"; 142 public final static String AUX_KEY = "aux"; 143 public final static String DOC_KEY = "doc"; 144 public final static String SPACING_BRIT = "1"; 145 public final static String SPACING_NON_BRIT = "4"; 146 147 /** The first projection we find */ 148 protected ProjectionImpl sampleProjection; 149 public MapProjection sampleMapProjection; 150 151 /** list of twod categories */ 152 private List twoDCategories; 153 154 /** list of 2D time series categories */ 155 private List twoDTimeSeriesCategories; 156 157 /** list of twod categories */ 158 private List bandCategories; 159 160 /** list of 2D time series categories */ 161 private List bandTimeSeriesCategories; 162 163 /* ADDE request string */ 164 private String source; 165 private String baseSource; 166 167 /* properties for this data source */ 168 private Hashtable sourceProps; 169 private Hashtable selectionProps; 170 171 private int lineResolution; 172 private int elementResolution; 173 private float lRes; 174 private float eRes; 175 private int lineMag = 1; 176 private int elementMag = 1; 177 178 private GeoSelection lastGeoSelection; 179 private DataChoice lastChoice = null; 180 private Boolean showPreview = Boolean.FALSE; 181 private FlatField previewImage = null; 182 private MapProjection previewProjection; 183 private Hashtable initProps; 184 185 private AreaDirectory previewDir = null; 186 private AREAnav previewNav = null; 187 private boolean haveDataSelectionComponents = false; 188 189 private GeoPreviewSelection previewSel; 190 private GeoLatLonSelection laLoSel; 191 192 private String choiceName; 193 194 private String saveCoordType; 195 private String savePlace; 196 private double saveLat; 197 private double saveLon; 198 private int saveNumLine; 199 private int saveNumEle; 200 private int saveLineMag; 201 private int saveEleMag; 202 private Boolean saveShowPreview; 203 204 private String displaySource; 205 206 protected List<DataChoice> stashedChoices = null; 207 private List iml = new ArrayList(); 208 private List saveImageList = new ArrayList(); 209 210 private int previewLineRes = 1; 211 private int previewEleRes = 1; 212 213 /** Whether or not this DataSource was loaded from a bundle. */ 214 private boolean fromBundle = false; 215 216 /** Are any of the data choices based upon remote files? */ 217 private boolean hasRemoteChoices = false; 218 219 public AddeImageParameterDataSource() {} 220 221 /** 222 * Creates a {@code AddeImageParameterDataSource} with a single ADDE URL. 223 * <b>Note:</b> the URLs should point at {@literal "image"} data. 224 * 225 * @param descriptor {@link ucar.unidata.data.DataSourceDescriptor DataSourceDescriptor} for this data source. 226 * @param image ADDE URL 227 * @param properties The properties for this data source. 228 * 229 * @throws VisADException 230 */ 231 public AddeImageParameterDataSource(DataSourceDescriptor descriptor, String image, 232 Hashtable properties) 233 throws VisADException { 234 super(descriptor, new String[] { image }, properties); 235 logger.trace("desc={}, image={}, properties={}", new Object[] { descriptor, image, properties }); 236 } 237 238 /** 239 * Create a new AddeImageParameterDataSource with an array of ADDE URL strings. 240 * <b>Note:</b> the URLs should point at {@literal "image"} data. 241 * 242 * @param descriptor {@link ucar.unidata.data.DataSourceDescriptor DataSourceDescriptor} for this data source. 243 * @param images Array of ADDE URLs. 244 * @param properties Properties for this data source. 245 * 246 * @throws VisADException 247 */ 248 public AddeImageParameterDataSource(DataSourceDescriptor descriptor, String[] images, 249 Hashtable properties) throws VisADException { 250 super(descriptor, images, properties); 251 logger.trace("desc={}, images={}, properties={}", new Object[] { descriptor, images, properties }); 252 } 253 254 /** 255 * Creates a new {@code AddeImageParameterDataSource} with an 256 * {@link java.util.List List} of ADDE URL strings. 257 * <b>Note:</b> the URLs should point at {@literal "image"} data. 258 * 259 * @param descriptor {@link ucar.unidata.data.DataSourceDescriptor DataSourceDescriptor} for this data source. 260 * @param images {@code List} of ADDE URL strings. 261 * @param properties Properties for this data source. 262 * 263 * @throws VisADException 264 */ 265 public AddeImageParameterDataSource(DataSourceDescriptor descriptor, List images, 266 Hashtable properties) throws VisADException { 267 super(descriptor, images, properties); 268 logger.trace("desc={}, images={}, properties={}", new Object[] { descriptor, images, properties }); 269 } 270 271 /** 272 * Create a new AddeImageParameterDataSource with the given dataset. 273 * 274 * @param descriptor {@link ucar.unidata.data.DataSourceDescriptor DataSourceDescriptor} for this data source. 275 * @param ids Dataset. 276 * @param properties Properties for this data source. 277 * 278 * @throws VisADException 279 */ 280 public AddeImageParameterDataSource(DataSourceDescriptor descriptor, ImageDataset ids, 281 Hashtable properties) throws VisADException { 282 super(descriptor, ids, properties); 283 logger.trace("desc={}, ids={}, properties={}", new Object[] { descriptor, ids, properties }); 284 this.sourceProps = properties; 285 if (properties.containsKey((Object)PREVIEW_KEY)) { 286 this.showPreview = (Boolean)(properties.get((Object)PREVIEW_KEY)); 287 saveShowPreview = showPreview; 288 } else { 289 if (saveShowPreview != null) { 290 showPreview = saveShowPreview; 291 } 292 } 293 294 List descs = ids.getImageDescriptors(); 295 AddeImageDescriptor aid = (AddeImageDescriptor)descs.get(0); 296 this.source = aid.getSource(); 297 if (this.source.contains("localhost")) { 298 AreaDirectory areaDirectory = aid.getDirectory(); 299 if (!sourceProps.containsKey((Object)UNIT_KEY)) { 300 if (!sourceProps.containsKey((Object)BAND_KEY)) { 301 String calType = areaDirectory.getCalibrationType(); 302 if (!calType.equals("RAW")) { 303 sourceProps.put(UNIT_KEY, calType); 304 int[] bandNums = areaDirectory.getBands(); 305 String bandString = new Integer(bandNums[0]).toString(); 306 sourceProps.put(BAND_KEY, bandString); 307 } 308 } 309 } 310 } 311 setMag(); 312 getAreaDirectory(properties); 313 } 314 315 @Override protected void propertiesChanged() { 316 logger.trace("fired"); 317 super.propertiesChanged(); 318 } 319 320 @Override protected boolean initDataFromPollingInfo() { 321 boolean result = super.initDataFromPollingInfo(); 322 logger.trace("result={}", result); 323 return result; 324 } 325 326 @Override protected boolean isPolling() { 327 boolean result = super.isPolling(); 328 logger.trace("isPolling={}", result); 329 return result; 330 } 331 332 @Override public void setPollingInfo(PollingInfo value) { 333 logger.trace("value={}", value); 334 super.setPollingInfo(value); 335 } 336 337 @Override protected boolean hasPollingInfo() { 338 boolean result = super.hasPollingInfo(); 339 logger.trace("hasPollingInfo={}", result); 340 return result; 341 } 342 343 @Override public PollingInfo getPollingInfo() { 344 PollingInfo result = super.getPollingInfo(); 345 logger.trace("getPollingInfo={}", result); 346 return result; 347 } 348 349 @Override public void initAfterUnpersistence() { 350 logger.trace("unbundled!"); 351 super.initAfterUnpersistence(); 352 353 if (this.sourceProps.containsKey(PREVIEW_KEY)) { 354 this.showPreview = (Boolean)this.sourceProps.get(PREVIEW_KEY); 355 if (this.showPreview == null) { 356 this.showPreview = Boolean.FALSE; 357 } 358 this.saveShowPreview = this.showPreview; 359 } 360 361 this.fromBundle = true; 362 List<AddeImageDescriptor> descriptors = (List<AddeImageDescriptor>)getImageList(); 363 this.source = descriptors.get(0).getSource(); // TODO: why not use the source from 364 // each AddeImageDescriptor? 365 for (AddeImageDescriptor descriptor : descriptors) { 366 if (!isFromFile(descriptor)) { 367 this.hasRemoteChoices = true; 368 break; 369 } 370 } 371 } 372 373 @Override public boolean canSaveDataToLocalDisk() { 374 return true; 375 } 376 377 private Hashtable<DataChoice, DataSelection> choiceToSel = new Hashtable<DataChoice, DataSelection>(); 378 379 public DataSelection getSelForChoice(final DataChoice choice) { 380 return choiceToSel.get(choice); 381 } 382 public boolean hasSelForChoice(final DataChoice choice) { 383 return choiceToSel.containsKey(choice); 384 } 385 public void putSelForChoice(final DataChoice choice, final DataSelection sel) { 386 choiceToSel.put(choice, sel); 387 } 388 389 /** 390 * Save files to local disk 391 * 392 * @param prefix destination dir and file prefix 393 * @param loadId For JobManager 394 * @param changeLinks Change internal file references 395 * 396 * @return Files copied 397 * 398 * @throws Exception On badness 399 */ 400 @Override protected List saveDataToLocalDisk(String prefix, Object loadId, boolean changeLinks) throws Exception { 401 logger.trace("prefix={} loadId={} changeLinks={}", new Object[] { prefix, loadId, changeLinks }); 402 final List<JCheckBox> checkboxes = new ArrayList<JCheckBox>(); 403 List categories = new ArrayList(); 404 Hashtable catMap = new Hashtable(); 405 Hashtable currentDataChoices = new Hashtable(); 406 407 List displays = getIdv().getDisplayControls(); 408 for (int i = 0; i < displays.size(); i++) { 409 List dataChoices = ((DisplayControl)displays.get(i)).getDataChoices(); 410 if (dataChoices == null) { 411 continue; 412 } 413 List finalOnes = new ArrayList(); 414 for (int j = 0; j < dataChoices.size(); j++) { 415 ((DataChoice)dataChoices.get(j)).getFinalDataChoices(finalOnes); 416 } 417 for (int dcIdx = 0; dcIdx < finalOnes.size(); dcIdx++) { 418 DataChoice dc = (DataChoice)finalOnes.get(dcIdx); 419 if (!(dc instanceof DirectDataChoice)) { 420 continue; 421 } 422 DirectDataChoice ddc = (DirectDataChoice) dc; 423 if (ddc.getDataSource() != this) { 424 continue; 425 } 426 currentDataChoices.put(ddc.getName(), ""); 427 } 428 } 429 430 for (int i = 0; i < dataChoices.size(); i++) { 431 DataChoice dataChoice = (DataChoice) dataChoices.get(i); 432 if (!(dataChoice instanceof DirectDataChoice)) { 433 continue; 434 } 435 436 // skip over datachoices that the user has not already loaded. 437 // (but fill the "slot" with null (it's a hack to signify that 438 // the "download" loop should skip over the data choice associated 439 // with this slot) 440 if (!currentDataChoices.containsKey(dataChoice.getName())) { 441 checkboxes.add(null); // 442 continue; 443 } 444 445 String label = dataChoice.getDescription(); 446 if (label.length() > 30) { 447 label = label.substring(0, 29) + "..."; 448 } 449 JCheckBox cbx = 450 new JCheckBox(label, 451 currentDataChoices.get(dataChoice.getName()) 452 != null); 453 ThreeDSize size = (ThreeDSize)dataChoice.getProperty(SIZE_KEY); 454 cbx.setToolTipText(dataChoice.getName()); 455 checkboxes.add(cbx); 456 DataCategory dc = dataChoice.getDisplayCategory(); 457 List comps = (List)catMap.get(dc); 458 if (comps == null) { 459 comps = new ArrayList(); 460 catMap.put(dc, comps); 461 categories.add(dc); 462 } 463 comps.add(cbx); 464 comps.add(GuiUtils.filler()); 465 if (size != null) { 466 JLabel sizeLabel = GuiUtils.rLabel(size.getSize() + " "); 467 sizeLabel.setToolTipText(size.getLabel()); 468 comps.add(sizeLabel); 469 } else { 470 comps.add(new JLabel("")); 471 } 472 } 473 final JCheckBox allCbx = new JCheckBox("Select All"); 474 allCbx.addActionListener(new ActionListener() { 475 public void actionPerformed(ActionEvent ae) { 476 for (JCheckBox cbx : checkboxes) { 477 if (cbx != null) { 478 cbx.setSelected(allCbx.isSelected()); 479 } 480 } 481 } 482 }); 483 List catComps = new ArrayList(); 484 JTabbedPane tab = new JTabbedPane(JTabbedPane.LEFT); 485 486 for (int i = 0; i < categories.size(); i++) { 487 List comps = (List)catMap.get(categories.get(i)); 488 JPanel innerPanel = GuiUtils.doLayout(comps, 3, GuiUtils.WT_NYN, GuiUtils.WT_N); 489 JScrollPane sp = new JScrollPane(GuiUtils.top(innerPanel)); 490 sp.setPreferredSize(new Dimension(500, 400)); 491 JPanel top = GuiUtils.right(GuiUtils.rLabel(" ")); 492 JComponent inner = GuiUtils.inset(GuiUtils.topCenter(top, sp), 5); 493 tab.addTab(categories.get(i).toString(), inner); 494 } 495 496 JComponent contents = tab; 497 contents = GuiUtils.topCenter( 498 GuiUtils.inset( 499 GuiUtils.leftRight( 500 new JLabel("Select the fields to download"), 501 allCbx), 5), contents); 502 JLabel label = new JLabel(getNameForDataSource(this, 50, true)); 503 contents = GuiUtils.topCenter(label, contents); 504 contents = GuiUtils.inset(contents, 5); 505 if (!GuiUtils.showOkCancelDialog(null, "", contents, null)) { 506 return null; 507 } 508 509 // iterate through user's selection to build list of things to download 510 List<String> realUrls = new ArrayList<String>(); 511 List<AddeImageDescriptor> descriptorsToSave = new ArrayList<AddeImageDescriptor>(); 512 List<BandInfo> bandInfos = (List<BandInfo>)getProperty(PROP_BANDINFO, (Object)null); 513 List<BandInfo> savedBands = new ArrayList<BandInfo>(); 514 for (int i = 0; i < dataChoices.size(); i++) { 515 DataChoice dataChoice = (DataChoice)dataChoices.get(i); 516 if (!(dataChoice instanceof DirectDataChoice)) { 517 continue; 518 } 519 JCheckBox cbx = (JCheckBox)checkboxes.get(i); 520 if (cbx == null || !cbx.isSelected()) { 521 continue; 522 } 523 524 if (dataChoice.getDataSelection() == null) { 525 dataChoice.setDataSelection(getSelForChoice(dataChoice)); 526 } 527 logger.trace("selected choice={} id={}", dataChoice.getName(), dataChoice.getId()); 528 List<AddeImageDescriptor> descriptors = getDescriptors(dataChoice, dataChoice.getDataSelection()); 529 logger.trace("descriptors={}", descriptors); 530 531 BandInfo bandInfo; 532 Object dataChoiceId = dataChoice.getId(); 533 if (dataChoiceId instanceof BandInfo) { 534 bandInfo = (BandInfo)dataChoiceId; 535 } else { 536 bandInfo = bandInfos.get(0); 537 } 538 String preferredUnit = bandInfo.getPreferredUnit(); 539 List<TwoFacedObject> filteredCalUnits = new ArrayList<TwoFacedObject>(); 540 for (TwoFacedObject tfo : (List<TwoFacedObject>)bandInfo.getCalibrationUnits()) { 541 if (preferredUnit.equals(tfo.getId())) { 542 filteredCalUnits.add(tfo); 543 } 544 } 545 bandInfo.setCalibrationUnits(filteredCalUnits); 546 savedBands.add(bandInfo); 547 548 DataSelection selection = dataChoice.getDataSelection(); 549 if (selection == null) { 550 if (getSelForChoice(dataChoice) != null) { 551 selection = getSelForChoice(dataChoice); 552 } else { 553 selection = getDataSelection(); 554 } 555 } 556 557 Hashtable selectionProperties = selection.getProperties(); 558 // Hashtable selectionProperties; 559 // if (selection != null) { 560 // selectionProperties = selection.getProperties(); 561 // } else { 562 // DataSelection sel = this.getDataSelection(); 563 // selectionProperties = new Hashtable(); 564 // } 565 logger.trace("bandinfo.getUnit={} selection props={}", bandInfo.getPreferredUnit(), selectionProperties); 566 for (AddeImageDescriptor descriptor : descriptors) { 567 // AddeImageInfo aii = (AddeImageInfo)descriptor.getImageInfo().clone(); 568 String src = descriptor.getSource(); 569 logger.trace("src before={}", src); 570 src = replaceKey(src, AddeImageURL.KEY_UNIT, bandInfo.getPreferredUnit()); 571 if (selectionProperties.containsKey(AddeImageURL.KEY_PLACE)) { 572 src = replaceKey(src, AddeImageURL.KEY_PLACE, selectionProperties.get(AddeImageURL.KEY_PLACE)); 573 } 574 if (selectionProperties.containsKey(AddeImageURL.KEY_LATLON)) { 575 src = replaceKey(src, AddeImageURL.KEY_LINEELE, AddeImageURL.KEY_LATLON, selectionProperties.get(AddeImageURL.KEY_LATLON)); 576 } 577 if (selectionProperties.containsKey(AddeImageURL.KEY_LINEELE)) { 578 src = removeKey(src, AddeImageURL.KEY_LATLON); 579 src = replaceKey(src, AddeImageURL.KEY_LINEELE, selectionProperties.get(AddeImageURL.KEY_LINEELE)); 580 } 581 if (selectionProperties.containsKey(AddeImageURL.KEY_MAG)) { 582 src = replaceKey(src, AddeImageURL.KEY_MAG, selectionProperties.get(AddeImageURL.KEY_MAG)); 583 } 584 if (selectionProperties.containsKey(AddeImageURL.KEY_SIZE)) { 585 src = replaceKey(src, AddeImageURL.KEY_SIZE, selectionProperties.get(AddeImageURL.KEY_SIZE)); 586 } 587 logger.trace("src after={}", src); 588 descriptor.setSource(src); 589 descriptorsToSave.add(descriptor); 590 } 591 // descriptorsToSave.addAll(descriptors); 592 } 593 if (!savedBands.isEmpty()) { 594 setProperty(PROP_BANDINFO, savedBands); 595 } 596 if (descriptorsToSave.isEmpty()) { 597 return null; 598 } 599 600 //Start the load, showing the dialog 601 List<String> suffixes = new ArrayList<String>(); 602 SimpleDateFormat sdf = new SimpleDateFormat("_" + DATAPATH_DATE_FORMAT); 603 sdf.setTimeZone(TimeZone.getTimeZone("GMT")); 604 for (int i = 0; i < descriptorsToSave.size(); i++) { 605 AddeImageDescriptor descriptor = descriptorsToSave.get(i); 606 AddeImageInfo aii = descriptor.getImageInfo(); 607 DateTime dttm = (DateTime)timeMap.get(descriptor.getSource()); 608 if (dttm != null) { 609 suffixes.add(sdf.format(ucar.visad.Util.makeDate(dttm)) + ".area"); 610 } else if (aii != null) { 611 String suffix = "_Band"+aii.getBand()+"_Unit"+aii.getUnit()+"_Pos"+i+".area"; 612 suffixes.add(suffix); 613 logger.trace("test suffix={}", suffix); 614 } else { 615 suffixes.add(i + ".area"); 616 } 617 realUrls.add(descriptor.getSource()); 618 } 619 logger.trace("urls={}", realUrls); 620 logger.trace("prefix={}", prefix); 621 logger.trace("suffixes={}", suffixes); 622 logger.trace("loadId={}", loadId); 623 List newFiles = IOUtil.writeTo(realUrls, prefix, suffixes, loadId); 624 logger.trace("files={}", newFiles); 625 if (newFiles == null) { 626 logger.trace("failed while in writeTo?"); 627 return null; 628 } else { 629 logger.trace("finished writeTo!"); 630 } 631 if (changeLinks) { 632 imageList = newFiles; 633 } 634 635 // write 0 as the first word 636 for (int i = 0; i < newFiles.size(); i++) { 637 try { 638 RandomAccessFile to = new RandomAccessFile((String)newFiles.get(i), "rw"); 639 to.seek(0); 640 to.writeInt(0); 641 to.close(); 642 } catch (Exception e) { 643 logger.error("unable to set first word to zero", e); 644 } 645 } 646 647 648 // if (geoSubset != null) { 649 // geoSubset.clearStride(); 650 // geoSubset.setBoundingBox(null); 651 // if (geoSelectionPanel != null) { 652 // geoSelectionPanel.initWith(doMakeGeoSelectionPanel()); 653 // } 654 // } 655 656 // List newFiles = Misc.newList(path); 657 // if (changeLinks) { 658 // //Get rid of the resolver URL 659 // getProperties().remove(PROP_RESOLVERURL); 660 // setNewFiles(newFiles); 661 // } 662 // 663 logger.trace("returning={}", newFiles); 664 return newFiles; 665 } 666 667 @Override protected String getDataPrefix() { 668 String tmp = StringUtil.replace(getName(), ' ', ""); 669 tmp = StringUtil.replace(tmp, '/', ""); 670 tmp = StringUtil.replace(tmp, "(AllBands)", ""); 671 tmp = IOUtil.cleanFileName(tmp); 672 logger.trace("data prefix={}", tmp); 673 return tmp; 674 } 675 676 /** 677 * A utility method that helps us deal with legacy bundles that used to 678 * have String file names as the id of a data choice. 679 * 680 * @param object May be an AddeImageDescriptor (for new bundles) or a 681 * String that is converted to an image descriptor. 682 * @return The image descriptor. 683 */ 684 @Override public AddeImageDescriptor getDescriptor(Object object) { 685 // logger.trace("--------------------"); 686 if (object == null) { 687 // logger.trace("null obj"); 688 return null; 689 } 690 if (object instanceof DataChoice) { 691 object = ((DataChoice)object).getId(); 692 logger.trace("datachoice getId={}", object); 693 } 694 if (object instanceof ImageDataInfo) { 695 int index = ((ImageDataInfo) object).getIndex(); 696 if (index < myDataChoices.size()) { 697 DataChoice dc = (DataChoice)myDataChoices.get(index); 698 Object tmpObject = dc.getId(); 699 if (tmpObject instanceof ImageDataInfo) { 700 // logger.trace("returning imagedatainfo"); 701 return ((ImageDataInfo)tmpObject).getAid(); 702 } 703 } 704 // logger.trace("invalid idx for imagedatainfo? (idx={} vs size={})", index, myDataChoices.size()); 705 return null; 706 // return ((ImageDataInfo) object).getAid(); 707 } 708 709 if (object instanceof AddeImageDescriptor) { 710 // logger.trace("already addeimagedesc! desc={}", object); 711 return (AddeImageDescriptor)object; 712 } 713 AddeImageDescriptor tmp = new AddeImageDescriptor(object.toString()); 714 // logger.trace("return descriptor={}", tmp); 715 // logger.trace("--------------------"); 716 return tmp; 717 } 718 719 /** 720 * Overwrite base class method to return the name of this class. 721 * 722 * @return The name. 723 */ 724 public String getImageDataSourceName() { 725 return "Adde Image Data Source (Parameter)"; 726 } 727 728 private void setMag() { 729 Object magKey = (Object)"mag"; 730 if (sourceProps.containsKey(magKey)) { 731 String magVal = (String)(sourceProps.get(magKey)); 732 String[] magVals = magVal.split(" "); 733 this.lineMag = new Integer(magVals[0]).intValue(); 734 this.elementMag = new Integer(magVals[1]).intValue(); 735 } 736 } 737 738 private void getAreaDirectory(Hashtable properties) { 739 String addeCmdBuff = source; 740 if (addeCmdBuff.contains("BAND=")) { 741 String bandStr = getKey(addeCmdBuff, "BAND"); 742 if (bandStr.length() == 0) { 743 addeCmdBuff = replaceKey(addeCmdBuff, "BAND", "1"); 744 } 745 } 746 if (addeCmdBuff.contains("MAG=")) { 747 String[] segs = addeCmdBuff.split("MAG="); 748 String seg0 = segs[0]; 749 String seg1 = segs[1]; 750 int indx = seg1.indexOf("&"); 751 seg1 = seg1.substring(indx); 752 String magString = lineMag + " " + elementMag; 753 addeCmdBuff = seg0 + "MAG=" + magString + seg1; 754 } 755 addeCmdBuff = addeCmdBuff.replace("imagedata", "imagedir"); 756 AreaDirectoryList dirList = null; 757 try { 758 dirList = new AreaDirectoryList(addeCmdBuff); 759 } catch (Exception e) { 760 try { 761 List<BandInfo> bandInfos = (List<BandInfo>)getProperty(PROP_BANDINFO, (Object)null); 762 BandInfo bi = bandInfos.get(0); 763 String bandStr = new Integer(bi.getBandNumber()).toString(); 764 addeCmdBuff = replaceKey(addeCmdBuff, "BAND", bandStr); 765 dirList = new AreaDirectoryList(addeCmdBuff); 766 } catch (Exception eOpen) { 767 setInError(true); 768 logger.error("problem opening AREA file", eOpen); 769 } 770 } 771 772 try { 773 List areaDirs = dirList.getDirs(); 774 AreaDirectory ad = (AreaDirectory)areaDirs.get(0); 775 float[] res = getLineEleResolution(ad); 776 float resol = res[0]; 777 if (this.lineMag < 0) 778 resol *= Math.abs(this.lineMag); 779 this.lineResolution = ad.getValue(11); 780 this.lRes = resol; 781 resol = res[1]; 782 if (this.elementMag < 0) 783 resol *= Math.abs(this.elementMag); 784 this.elementResolution = ad.getValue(12); 785 this.eRes = resol; 786 } catch (Exception e) { 787 setInError(true); 788 logger.error("getting area directory", e); 789 } 790 baseSource = addeCmdBuff; 791 } 792 793 protected void initDataSelectionComponents( 794 List<DataSelectionComponent> components, final DataChoice dataChoice) { 795 796 if (fromBundle && !hasRemoteChoices) { 797 components.add(new BundlePreviewSelection("Region (Disabled)")); 798 components.add(new BundlePreviewSelection("Advanced (Disabled)")); 799 return; 800 } 801 802 getDataContext().getIdv().showWaitCursor(); 803 804 boolean hasImagePreview = true; 805 if (this.showPreview == null) { 806 this.showPreview = true; 807 } 808 boolean basically = false; 809 if (this.lastChoice != null) { 810 basically = dataChoice.basicallyEquals(this.lastChoice); 811 } 812 logger.trace("dataChoice={}", dataChoice); 813 // check for comps and whether or not dataChoice is hooping right back into line 814 if (this.haveDataSelectionComponents && dataChoice.equals(this.lastChoice)) { 815 try { 816 // did the datachoice ever actually get data? 817 if (dataChoice.getDataSelection() == null) { 818 if (!basically) { 819 this.laLoSel = new GeoLatLonSelection(this, 820 dataChoice, this.initProps, this.previewProjection, 821 previewDir, previewNav); 822 } 823 this.lineMag = this.laLoSel.getLineMag(); 824 this.elementMag = this.laLoSel.getElementMag(); 825 826 /* DAVEP: Force preview on. "No preview" means blank image */ 827 // this.previewSel = new GeoPreviewSelection(this, dataChoice, this.previewImage, 828 // this.laLoSel, this.previewProjection, 829 // this.lineMag, this.elementMag, this.showPreview); 830 this.previewSel = new GeoPreviewSelection(this, dataChoice, this.previewImage, 831 this.laLoSel, this.previewProjection, 832 this.lineMag, this.elementMag, true); 833 } 834 components.add(this.previewSel); 835 components.add(this.laLoSel); 836 } catch (Exception e) { 837 logger.error("error while repeating addition of selection components", e); 838 getDataContext().getIdv().showNormalCursor(); 839 } 840 } else { 841 try { 842 hasImagePreview = makePreviewImage(dataChoice); 843 if (basically) { 844 getSaveComponents(); 845 } 846 } catch (Exception e) { 847 JLabel label = new JLabel("Can't make preview image"); 848 JPanel contents = GuiUtils.top(GuiUtils.inset(label, label.getText().length() + 12)); 849 GuiUtils.showOkDialog(null, "No Preview Image", contents, null); 850 getDataContext().getIdv().showNormalCursor(); 851 logger.error("problem creating preview image", e); 852 return; 853 } 854 this.lastChoice = dataChoice; 855 if (hasImagePreview) { 856 try { 857 String magStr = getKey(baseSource, MAG_KEY); 858 String saveMagStr = magStr; 859 String[] vals = StringUtil.split(magStr, " ", 2); 860 Integer iVal = new Integer(vals[0]); 861 int lMag = iVal.intValue() * -1; 862 if (lMag == -1) { 863 lMag = 1; 864 } 865 iVal = new Integer(vals[1]); 866 int eMag = iVal.intValue() * -1; 867 if (eMag == -1) { 868 eMag = 1; 869 } 870 magStr = lMag + " " + eMag; 871 replaceKey(MAG_KEY, magStr); 872 // String saveStr = baseSource; 873 // if (!showPreview) { 874 // replaceKey(SIZE_KEY, "2 2"); 875 // } 876 AreaAdapter aa = null; 877 AREACoordinateSystem acs = null; 878 try { 879 880 if (showPreview) { 881 aa = new AreaAdapter(baseSource, false); 882 this.previewImage = (FlatField)aa.getImage(); 883 } 884 else { 885 this.previewImage = Util.makeField(0, 1, 1, 0, 1, 1, 0, "TEMP"); 886 } 887 888 AreaFile af = new AreaFile(baseSource); 889 previewNav = af.getNavigation(); 890 AreaDirectory ad = af.getAreaDirectory(); 891 this.lineResolution = ad.getValue(11); 892 this.elementResolution = ad.getValue(12); 893 acs = new AREACoordinateSystem(af); 894 } catch (Exception e) { 895 String excp = e.toString(); 896 int indx = excp.lastIndexOf(":"); 897 String errorText = excp.substring(indx+1); 898 JLabel label = new JLabel(errorText); 899 JPanel contents = GuiUtils.top(GuiUtils.inset(label, label.getText().length() + 12)); 900 GuiUtils.showOkDialog(null, "Can't Make Geographical Selection Tabs", contents, null); 901 getDataContext().getIdv().showNormalCursor(); 902 logger.error("problem creating preview image", e); 903 return; 904 } 905 this.initProps = new Hashtable(); 906 Enumeration propEnum = sourceProps.keys(); 907 for (int i = 0; propEnum.hasMoreElements(); i++) { 908 String key = propEnum.nextElement().toString(); 909 Object val = sourceProps.get(key); 910 key = key.toUpperCase(); 911 if (val instanceof String) { 912 String str = (String)val; 913 val = (Object)(str.toUpperCase()); 914 } 915 this.initProps.put(key,val); 916 } 917 replaceKey(MAG_KEY, saveMagStr); 918 magStr = getKey(baseSource, MAG_KEY); 919 vals = StringUtil.split(magStr, " ", 2); 920 iVal = new Integer(vals[0]); 921 lMag = iVal.intValue(); 922 iVal = new Integer(vals[1]); 923 eMag = iVal.intValue(); 924 925 this.initProps.put("LRES", String.valueOf((this.lRes))); 926 this.initProps.put("ERES", String.valueOf((this.eRes))); 927 this.initProps.put("PLRES", String.valueOf((this.previewLineRes))); 928 this.initProps.put("PERES", String.valueOf((this.previewEleRes))); 929 this.previewProjection = (MapProjection)acs; 930 931 String coordType = ""; 932 double coords[] = { 0.0, 0.0 }; 933 934 logger.trace("basically={} laLoSel==null?={}", basically, (this.laLoSel==null)); 935 if (!basically) { 936 if (this.laLoSel != null) { 937 coordType = this.laLoSel.getCoordinateType(); 938 if (coordType.equals(this.laLoSel.getLatLonType())) { 939 coords[0] = this.laLoSel.getLatitude(); 940 coords[1] = this.laLoSel.getLongitude(); 941 } else { 942 coords[0] = (double)this.laLoSel.getLine(); 943 coords[1] = (double)this.laLoSel.getElement(); 944 } 945 946 // turns out that laLoSel is reused for datachoices 947 // from the same source. if you don't update laLoSel's 948 // dataChoice, it'll apply whatever data selection 949 // you set up... to the first data choice that you 950 // loaded! (and causing an NPE when attempting to 951 // bundle the dataselection for the newly-selected 952 // datachoice. 953 this.previewSel.setDataChoice(dataChoice); 954 this.laLoSel.setDataChoice(dataChoice); 955 this.laLoSel.setPreviewLineRes(this.previewLineRes); 956 this.laLoSel.setPreviewEleRes(this.previewEleRes); 957 this.laLoSel.update(previewDir, this.previewProjection, previewNav, 958 coordType, coords); 959 960 } else { 961 this.laLoSel = new GeoLatLonSelection(this, 962 dataChoice, this.initProps, this.previewProjection, 963 previewDir, previewNav); 964 this.lineMag = this.laLoSel.getLineMag(); 965 this.elementMag = this.laLoSel.getElementMag(); 966 } 967 } else { 968 if (this.laLoSel != null) { 969 this.previewSel.setDataChoice(dataChoice); 970 this.laLoSel.setDataChoice(dataChoice); 971 } 972 } 973 /* DAVEP: Force preview on. "No preview" means blank image */ 974 // this.previewSel = new GeoPreviewSelection(this, dataChoice, this.previewImage, 975 // this.laLoSel, this.previewProjection, 976 // this.lineMag, this.elementMag, this.showPreview); 977 this.previewSel = new GeoPreviewSelection(this, dataChoice, this.previewImage, 978 this.laLoSel, this.previewProjection, 979 this.lineMag, this.elementMag, true); 980 981 } catch (Exception e) { 982 logger.error("problem making selection components", e); 983 getDataContext().getIdv().showNormalCursor(); 984 } 985 this.haveDataSelectionComponents = true; 986 replaceKey(MAG_KEY, (Object)(this.lineMag + " " + this.elementMag)); 987 components.add(this.previewSel); 988 components.add(this.laLoSel); 989 } 990 } 991 if (this.previewSel != null) { 992 this.previewSel.initBox(); 993 } 994 getDataContext().getIdv().showNormalCursor(); 995 } 996 997 /** 998 * A hook to allow this data source to add data selection components 999 * to the IDV field selector 1000 * 1001 * @param dataChoice the data choice 1002 * 1003 * @return list of components 1004 */ 1005 // @Override public List<DataSelectionComponent> getDataSelectionComponents(DataChoice dataChoice) { 1006 //// List<DataSelectionComponent> dataSelectionComponents = new ArrayList<DataSelectionComponent>(); 1007 //// initDataSelectionComponents(dataSelectionComponents, dataChoice); 1008 //// return dataSelectionComponents; 1009 // return new ArrayList<DataSelectionComponent>(); 1010 // } 1011 1012 private boolean makePreviewImage(DataChoice dataChoice) { 1013 1014 getDataContext().getIdv().showWaitCursor(); 1015 1016 boolean msgFlag = false; 1017 showPreview = saveShowPreview; 1018 List<BandInfo> bandInfos = (List<BandInfo>) getProperty(PROP_BANDINFO, (Object) null); 1019 BandInfo bi = null; 1020 String saveBand = getKey(source, BAND_KEY); 1021 int bandIdx = 0; 1022 List<TwoFacedObject> calList = null; 1023 try { 1024 Object dcObj = dataChoice.getId(); 1025 if (dcObj instanceof BandInfo) { 1026 bi = (BandInfo) dcObj; 1027 Integer bandInt = new Integer(bandInfos.indexOf(dcObj)+1); 1028 saveBand = bandInt.toString(); 1029 } else { 1030 msgFlag = true; 1031 bi = bandInfos.get(bandIdx); 1032 this.showPreview = false; 1033 } 1034 // pull out the list of cal units, we'll need for type check later... 1035 calList = bi.getCalibrationUnits(); 1036 source = replaceKey(source, BAND_KEY, (Object) (bi.getBandNumber())); 1037 // if we're replacing the band, replace cal type with preferred 1038 // type for that band 1039 source = replaceKey(source, UNIT_KEY, (Object) bi.getPreferredUnit()); 1040 } catch (Exception excp) { 1041 handlePreviewImageError(1, excp); 1042 } 1043 String name = dataChoice.getName(); 1044 int idx = name.lastIndexOf("_"); 1045 String unit = name.substring(idx + 1); 1046 1047 // if this is not a valid cal unit (e.g. could be set to a plugin formula name) 1048 // set it to something valid 1049 boolean validCal = false; 1050 for (TwoFacedObject tfo : calList) { 1051 if (unit.equals((String) tfo.getId())) { 1052 validCal = true; 1053 break; 1054 } 1055 } 1056 if (!validCal) { 1057 unit = bi.getPreferredUnit(); 1058 } 1059 1060 if (getKey(source, UNIT_KEY).length() == 0) { 1061 source = replaceKey(source, UNIT_KEY, (Object)(unit)); 1062 } 1063 1064 AddeImageDescriptor aid = null; 1065 while (aid == null) { 1066 try { 1067 aid = new AddeImageDescriptor(this.source); 1068 } catch (Exception excp) { 1069 msgFlag = true; 1070 if (bandIdx > bandInfos.size()) { 1071 return false; 1072 } 1073 bi = bandInfos.get(bandIdx); 1074 source = replaceKey(source, BAND_KEY, (Object)(bi.getBandNumber())); 1075 ++bandIdx; 1076 } 1077 } 1078 previewDir = getPreviewDirectory(aid); 1079 int eMag = 1; 1080 int lMag = 1; 1081 int eSize = 1; 1082 int lSize = 1; 1083 try { 1084 int plMag = 1; 1085 int peMag = 1; 1086 Object magKey = (Object)"mag"; 1087 if (sourceProps.containsKey(magKey)) { 1088 String magVal = (String)(sourceProps.get(magKey)); 1089 String[] magVals = magVal.split(" "); 1090 peMag = new Integer(magVals[0]).intValue(); 1091 plMag = new Integer(magVals[1]).intValue(); 1092 } 1093 double feSize = (double)previewDir.getElements(); 1094 double flSize = (double)previewDir.getLines(); 1095 double feMag = (double)peMag; 1096 double flMag = (double)plMag; 1097 if (feSize > flSize) { 1098 feMag = feSize/525.0; 1099 flMag = feMag * (double)plMag/(double)peMag; 1100 } else { 1101 flMag = flSize/500.0; 1102 feMag = flMag * (double)peMag/(double)plMag; 1103 } 1104 eMag = (int)Math.ceil(feMag); 1105 lMag = (int)Math.ceil(flMag); 1106 } catch(Exception excp) { 1107 handlePreviewImageError(3, excp); 1108 } 1109 if (eMag < 1) eMag = 1; 1110 if (lMag < 1) lMag = 1; 1111 1112 eSize = 525; 1113 lSize = 500; 1114 if ((baseSource == null) || msgFlag) { 1115 baseSource = source; 1116 } 1117 this.previewLineRes = lMag; 1118 this.previewEleRes = eMag; 1119 String uLStr = "0 0 F"; 1120 try { 1121 int startLine = previewDir.getValue(5); 1122 int startEle = previewDir.getValue(6); 1123 uLStr = startLine + " " + startEle + " I"; 1124 } catch (Exception e) { 1125 } 1126 String src = aid.getSource(); 1127 1128 src = removeKey(src, LATLON_KEY); 1129 src = replaceKey(src, LINELE_KEY, (Object)uLStr); 1130 src = replaceKey(src, PLACE_KEY, (Object)("ULEFT")); 1131 src = replaceKey(src, SIZE_KEY, (Object)(lSize + " " + eSize)); 1132 src = replaceKey(src, MAG_KEY, (Object)(lMag + " " + eMag)); 1133 src = replaceKey(src, BAND_KEY, (Object)(bi.getBandNumber())); 1134 src = replaceKey(src, UNIT_KEY, (Object)(unit)); 1135 1136 try { 1137 aid = new AddeImageDescriptor(src); 1138 } catch (Exception excp) { 1139 handlePreviewImageError(4, excp); 1140 src = replaceKey(src, BAND_KEY, (Object)saveBand); 1141 aid = new AddeImageDescriptor(src); 1142 src = replaceKey(src, BAND_KEY, (Object)(bi.getBandNumber())); 1143 } 1144 if (msgFlag && (!"ALL".equals(saveBand))) { 1145 src = replaceKey(src, BAND_KEY, (Object)saveBand); 1146 } 1147 baseSource = src; 1148 1149 getDataContext().getIdv().showNormalCursor(); 1150 1151 return true; 1152 } 1153 1154 /** 1155 * Show the given error to the user. 1156 * 1157 * @param excp The exception 1158 */ 1159 protected void handlePreviewImageError(int flag, Exception excp) { 1160 getDataContext().getIdv().showNormalCursor(); 1161 LogUtil.userErrorMessage("Error in makePreviewImage e=" + flag + " " + excp); 1162 } 1163 1164 private String removeKey(String src, String key) { 1165 String returnString = src; 1166 key = key.toUpperCase() + '='; 1167 if (returnString.contains(key)) { 1168 String[] segs = returnString.split(key); 1169 String seg0 = segs[0]; 1170 String seg1 = segs[1]; 1171 int indx = seg1.indexOf("&"); 1172 if (indx >= 0) { 1173 seg1 = seg1.substring(indx+1); 1174 } 1175 returnString = seg0 + seg1; 1176 } 1177 return returnString; 1178 } 1179 1180 private String replaceKey(String src, String key, Object val) { 1181 String returnString = src; 1182 // make sure we got valid key/val pair 1183 if ((key == null) || (val == null)) { 1184 return returnString; 1185 } 1186 key = key.toUpperCase() + '='; 1187 if (returnString.contains(key)) { 1188 String[] segs = returnString.split(key); 1189 String seg0 = segs[0]; 1190 String seg1 = segs[1]; 1191 int indx = seg1.indexOf("&"); 1192 if (indx < 0) { 1193 seg1 = ""; 1194 } else if (indx > 0) { 1195 seg1 = seg1.substring(indx); 1196 } 1197 returnString = seg0 + key + val + seg1; 1198 } else { 1199 returnString = returnString + '&' + key + val; 1200 } 1201 // if key is for cal units, and it was changed to BRIT, 1202 // must change the spacing key too 1203 if ((key.equals(UNIT_KEY + "=")) && ("BRIT".equals(val))) { 1204 returnString = replaceKey(returnString, SPAC_KEY, SPAC_KEY, SPACING_BRIT); 1205 } else { 1206 returnString = replaceKey(returnString, SPAC_KEY, SPAC_KEY, SPACING_NON_BRIT); 1207 } 1208 return returnString; 1209 } 1210 1211 private String replaceKey(String src, String oldKey, String newKey, Object val) { 1212 String returnString = src; 1213 oldKey = oldKey.toUpperCase() + '='; 1214 newKey = newKey.toUpperCase() + '='; 1215 if (returnString.contains(oldKey)) { 1216 String[] segs = returnString.split(oldKey); 1217 String seg0 = segs[0]; 1218 String seg1 = segs[1]; 1219 int indx = seg1.indexOf("&"); 1220 if (indx < 0) { 1221 seg1 = ""; 1222 } else if (indx > 0) { 1223 seg1 = seg1.substring(indx); 1224 } 1225 returnString = seg0 + newKey + val + seg1; 1226 } 1227 else { 1228 returnString = returnString + '&' + newKey + val; 1229 } 1230 return returnString; 1231 } 1232 1233 private void replaceKey(String key, Object val) { 1234 baseSource = replaceKey(baseSource, key, val); 1235 } 1236 1237 private String getKey(String src, String key) { 1238 String returnString = ""; 1239 key = key.toUpperCase() + '='; 1240 if (src.contains(key)) { 1241 String[] segs = src.split(key); 1242 segs = segs[1].split("&"); 1243 returnString = segs[0]; 1244 } 1245 return returnString; 1246 } 1247 1248 1249 /** 1250 * Create the set of {@link ucar.unidata.data.DataChoice} that represent 1251 * the data held by this data source. We create one top-level 1252 * {@link ucar.unidata.data.CompositeDataChoice} that represents 1253 * all of the image time steps. We create a set of children 1254 * {@link ucar.unidata.data.DirectDataChoice}, one for each time step. 1255 */ 1256 public void doMakeDataChoices() { 1257 super.doMakeDataChoices(); 1258 List<BandInfo> bandInfos = (List<BandInfo>)getProperty(PROP_BANDINFO, (Object)null); 1259 String name = ""; 1260 if (this.choiceName != null) { 1261 name = this.choiceName; 1262 } 1263 if (name.length() != 0) { 1264 logger.trace("already have a name={}", name); 1265 return; 1266 } 1267 if (!sourceProps.containsKey(UNIT_KEY)) { 1268 logger.trace("sourceProps has no unit key={}", sourceProps); 1269 return; 1270 } 1271 BandInfo bi = null; 1272 if (sourceProps.containsKey(BAND_KEY)) { 1273 int bandProp = new Integer((String)(sourceProps.get(BAND_KEY))).intValue(); 1274 int bandIndex = BandInfo.findIndexByNumber(bandProp, bandInfos); 1275 bi = (BandInfo)bandInfos.get(bandIndex); 1276 if (sourceProps.containsKey(UNIT_KEY)) { 1277 bi.setPreferredUnit((String)(sourceProps.get(UNIT_KEY))); 1278 } else { 1279 bi.setPreferredUnit(""); 1280 } 1281 name = makeBandParam(bi); 1282 } 1283 else if (sourceProps.containsKey(BANDINFO_KEY)) { 1284 ArrayList al = (ArrayList)sourceProps.get(BANDINFO_KEY); 1285 bi = (BandInfo)al.get(0); 1286 name = makeBandParam(bi); 1287 } 1288 if (stashedChoices != null) { 1289 int numChoices = stashedChoices.size(); 1290 for (int i = 0; i < numChoices; i++) { 1291 DataChoice choice = (DataChoice)stashedChoices.get(i); 1292 if (name.equals(choice.getName())) { 1293 setProperty(PROP_DATACHOICENAME, choice.getName()); 1294 } 1295 } 1296 } 1297 } 1298 1299 /** 1300 * Overridden so that McIDAS-V can <i>attempt</i> to return the correct 1301 * {@code DataSelection} for the current {@code DataChoice}. 1302 */ 1303 @Override public DataSelection getDataSelection() { 1304 DataSelection tmp; 1305 if (this.laLoSel == null || this.choiceToSel == null || !this.choiceToSel.containsKey(this.laLoSel.getDataChoice())) { 1306 logger.trace("* idvland getDataSelection"); 1307 tmp = super.getDataSelection(); 1308 } else { 1309 logger.trace("* mcv getSelForChoice"); 1310 tmp = this.getSelForChoice(this.laLoSel.getDataChoice()); 1311 } 1312 logger.trace("return selection props={} geo={}", tmp.getProperties(), tmp.getGeoSelection()); 1313 return tmp; 1314 } 1315 1316 /** 1317 * Overridden so that McIDAS-V can associate this data source's current 1318 * {@code DataChoice} with the given {@code DataSelection}. 1319 */ 1320 @Override public void setDataSelection(DataSelection s) { 1321 super.setDataSelection(s); 1322 if (this.laLoSel != null) { 1323 this.putSelForChoice(this.laLoSel.getDataChoice(), s); 1324 } 1325 logger.trace("setting selection props={} geo={}", s.getProperties(), s.getGeoSelection()); 1326 } 1327 1328 // @Override public int canShowParameter(String name) { 1329 // int result = super.canShowParameter(name); 1330 // switch (result) { 1331 // case 0: //show=yes 1332 // logger.trace("can show param={}", name); 1333 // break; 1334 // case 1: // show=hide 1335 // logger.trace("hide param={}", name); 1336 // break; 1337 // case 2: // show=no 1338 // logger.trace("no show param={}", name); 1339 // break; 1340 // default: 1341 // logger.trace("trouble for param={}", name); 1342 // break; 1343 // } 1344 // return result; 1345 // 1346 // } 1347 1348 /** 1349 * Insert the new DataChoice into the dataChoice list. 1350 * 1351 * @param choice new choice to add 1352 */ 1353 protected void addDataChoice(DataChoice choice) { 1354 logger.trace("choice={}", choice); 1355 super.addDataChoice(choice); 1356 if (stashedChoices == null) { 1357 stashedChoices = new ArrayList(); 1358 } 1359 stashedChoices.add(choice); 1360 } 1361 1362 1363 /** 1364 * Initialize the {@link ucar.unidata.data.DataCategory} objects that 1365 * this data source uses. 1366 */ 1367 private void makeCategories() { 1368 twoDTimeSeriesCategories = 1369 DataCategory.parseCategories("IMAGE-2D-TIME;", false); 1370 twoDCategories = DataCategory.parseCategories("IMAGE-2D;", false); 1371 bandCategories = DataCategory.parseCategories("IMAGE-BAND;", false); 1372 bandTimeSeriesCategories = 1373 DataCategory.parseCategories("IMAGE-BAND-TIME;", false); 1374 1375 } 1376 1377 /** 1378 * Checks to see if a given {@code AddeImageDescriptor} is based upon a 1379 * local (or remote) file. 1380 * 1381 * <p>The check is pretty simple: is {@code descriptor.getSource()} a valid 1382 * path? 1383 * 1384 * @param descriptor {@code AddeImageDescriptor} of questionable origins. Shouldn't be {@code null}. 1385 * 1386 * @return {@code true} if {@code descriptor}'s source is a valid path. 1387 */ 1388 public static boolean isFromFile(final AddeImageDescriptor descriptor) { 1389 return new File(descriptor.getSource()).exists(); 1390 } 1391 1392 /** 1393 * Create the actual data represented by the given 1394 * {@link ucar.unidata.data.DataChoice}. 1395 * 1396 * @param dataChoice Either the 1397 * {@link ucar.unidata.data.CompositeDataChoice} 1398 * representing all time steps or a 1399 * {@link ucar.unidata.data.DirectDataChoice} 1400 * representing a single time step. 1401 * @param category Not really used. 1402 * @param dataSelection Defines any time subsets. 1403 * @param requestProperties extra request properties 1404 * 1405 * @return The image or image sequence data. 1406 * 1407 * @throws RemoteException Java RMI problem 1408 * @throws VisADException VisAD problem 1409 */ 1410 protected Data getDataInner(DataChoice dataChoice, DataCategory category, 1411 DataSelection dataSelection, 1412 Hashtable requestProperties) 1413 throws VisADException, RemoteException { 1414 Data img = null; 1415 iml = new ArrayList(); 1416 1417 if (dataSelection == null) { 1418 return null; 1419 } 1420 setDataSelection(dataSelection); 1421 1422 GeoSelection geoSelection = dataSelection.getGeoSelection(true); 1423 if (geoSelection == null) { 1424 return null; 1425 } 1426 1427 boolean validState = geoSelection.getHasValidState(); 1428 if (!validState) { 1429 return null; 1430 } 1431 1432 if (this.lastGeoSelection == null) { 1433 this.lastGeoSelection = geoSelection; 1434 } 1435 1436 this.selectionProps = dataSelection.getProperties(); 1437 Enumeration propEnum = this.selectionProps.keys(); 1438 for (int i = 0; propEnum.hasMoreElements(); i++) { 1439 String key = propEnum.nextElement().toString(); 1440 if (key.compareToIgnoreCase(LATLON_KEY) == 0) { 1441 String val = (String)this.selectionProps.get(key); 1442 if (val.contains("NaN")) { 1443 return img; 1444 } 1445 } 1446 if (key.compareToIgnoreCase(LINELE_KEY) == 0) { 1447 String val = (String)this.selectionProps.get(key); 1448 if (val.contains("NaN")) { 1449 return img; 1450 } 1451 } 1452 } 1453 1454 if (this.selectionProps.containsKey("MAG")) { 1455 String str = (String)this.selectionProps.get("MAG"); 1456 String[] strs = StringUtil.split(str, " ", 2); 1457 this.lineMag = new Integer(strs[0]).intValue(); 1458 this.elementMag = new Integer(strs[1]).intValue(); 1459 } 1460 this.choiceName = dataChoice.getName(); 1461 if (this.choiceName != null) { 1462 setProperty(PROP_DATACHOICENAME, this.choiceName); 1463 } 1464 try { 1465 img = super.getDataInner(dataChoice, category, dataSelection, requestProperties); 1466 } catch (Exception e) { 1467 String displaySrc = getDisplaySource(); 1468 if (displaySrc != null) { 1469 AddeImageDescriptor aid = new AddeImageDescriptor(displaySrc); 1470 dataChoice.setId((Object)aid); 1471 img = super.getDataInner(dataChoice, category, dataSelection, requestProperties); 1472 } 1473 } 1474 return img; 1475 } 1476 1477 /** 1478 * Check if the DataChoice has a BandInfo for it's Id 1479 * 1480 * @param dataChoice choice to check 1481 * 1482 * @return true if the choice ID is a BandInfo 1483 */ 1484 private boolean hasBandInfo(DataChoice dataChoice) { 1485 Object id = dataChoice.getId(); 1486 return id instanceof BandInfo; 1487 } 1488 1489 /** _more_ */ 1490 AreaDirectory[][] currentDirs; 1491 1492 /** 1493 * Create the image sequence defined by the given dataChoice. 1494 * 1495 * @param dataChoice The choice. 1496 * @param subset any time subsets. 1497 * @return The image sequence. 1498 * 1499 * @throws RemoteException Java RMI problem 1500 * @throws VisADException VisAD problem 1501 */ 1502 protected ImageSequence makeImageSequence(DataChoice dataChoice, 1503 DataSelection subset) 1504 throws VisADException, RemoteException { 1505 1506 // if (dataChoice.getDataSelection() == null) { 1507 // dataChoice.setDataSelection(subset); 1508 // } 1509 Hashtable subsetProperties = subset.getProperties(); 1510 Enumeration propEnum = subsetProperties.keys(); 1511 int numLines = 0; 1512 int numEles = 0; 1513 for (int i=0; propEnum.hasMoreElements(); i++) { 1514 String key = propEnum.nextElement().toString(); 1515 if (key.compareToIgnoreCase(SIZE_KEY) == 0) { 1516 String sizeStr = (String)(subsetProperties.get(key)); 1517 String[] vals = StringUtil.split(sizeStr, " ", 2); 1518 Integer iVal = new Integer(vals[0]); 1519 numLines = iVal.intValue(); 1520 iVal = new Integer(vals[1]); 1521 numEles = iVal.intValue(); 1522 break; 1523 } 1524 } 1525 1526 if (sampleMapProjection == null) { 1527 String addeCmdBuff = baseSource; 1528 AreaFile af = null; 1529 try { 1530 af = new AreaFile(addeCmdBuff); 1531 } catch (Exception eOpen) { 1532 logger.error("could not open area file: {}", eOpen); 1533 setInError(true); 1534 throw new BadDataException("Opening area file: " + eOpen.getMessage()); 1535 } 1536 try { 1537 McIDASAreaProjection map = new McIDASAreaProjection(af); 1538 AREACoordinateSystem acs = new AREACoordinateSystem(af); 1539 sampleMapProjection = (MapProjection)acs; 1540 sampleProjection = map; 1541 } catch (Exception e) { 1542 logger.error("making area projection: {}", e); 1543 setInError(true); 1544 throw new BadDataException("Making area projection: " + e.getMessage()); 1545 } 1546 } 1547 AREACoordinateSystem macs = (AREACoordinateSystem)sampleMapProjection; 1548 int[] dirBlk = macs.getDirBlock(); 1549 if (numLines == 0) { 1550 double elelin[][] = new double[2][2]; 1551 double latlon[][] = new double[2][2]; 1552 GeoSelection gs = subset.getGeoSelection(); 1553 GeoLocationInfo gli = gs.getBoundingBox(); 1554 if ((gli == null) && (lastGeoSelection != null)) { 1555 subset.setGeoSelection(lastGeoSelection); 1556 gs = lastGeoSelection; 1557 gli = gs.getBoundingBox(); 1558 } 1559 LatLonPoint llp = gli.getUpperLeft(); 1560 latlon[0][0] = llp.getLatitude(); 1561 latlon[1][0] = llp.getLongitude(); 1562 llp = gli.getLowerRight(); 1563 latlon[0][1] = llp.getLatitude(); 1564 latlon[1][1] = llp.getLongitude(); 1565 elelin = macs.fromReference(latlon); 1566 numLines = (int)(Math.abs(elelin[1][0] - elelin[1][1]))*dirBlk[11]; 1567 numEles = (int)(Math.abs(elelin[0][1] - elelin[0][0]))*dirBlk[12]; 1568 } 1569 1570 try { 1571 List descriptorsToUse = new ArrayList(); 1572 if (hasBandInfo(dataChoice)) { 1573 descriptorsToUse = getDescriptors(dataChoice, subset); 1574 } else { 1575 List choices = (dataChoice instanceof CompositeDataChoice) 1576 ? getChoicesFromSubset( 1577 (CompositeDataChoice) dataChoice, subset) 1578 : Arrays.asList(new DataChoice[] { 1579 dataChoice }); 1580 for (Iterator iter = choices.iterator(); iter.hasNext(); ) { 1581 DataChoice subChoice = (DataChoice) iter.next(); 1582 AddeImageDescriptor aid = 1583 getDescriptor(subChoice.getId()); 1584 if (aid == null) { 1585 continue; 1586 } 1587 DateTime dttm = aid.getImageTime(); 1588 if ((subset != null) && (dttm != null)) { 1589 List times = getTimesFromDataSelection(subset, 1590 dataChoice); 1591 if ((times != null) && (times.indexOf(dttm) == -1)) { 1592 continue; 1593 } 1594 } 1595 descriptorsToUse.add(aid); 1596 } 1597 } 1598 1599 if (descriptorsToUse.size() == 0) { 1600 return null; 1601 } 1602 AddeImageInfo biggestPosition = null; 1603 int pos = 0; 1604 boolean anyRelative = false; 1605 // Find the descriptor with the largets position 1606 for (Iterator iter = 1607 descriptorsToUse.iterator(); iter.hasNext(); ) { 1608 AddeImageDescriptor aid = (AddeImageDescriptor) iter.next(); 1609 if (aid.getIsRelative()) { 1610 anyRelative = true; 1611 } 1612 AddeImageInfo aii = aid.getImageInfo(); 1613 1614 //Are we dealing with area files here? 1615 if (aii == null) { 1616 break; 1617 } 1618 1619 //Check if this is absolute time 1620 if ((aii.getStartDate() != null) 1621 || (aii.getEndDate() != null)) { 1622 biggestPosition = null; 1623 break; 1624 } 1625 if ((biggestPosition == null) 1626 || (Math.abs(aii.getDatasetPosition()) > pos)) { 1627 pos = Math.abs(aii.getDatasetPosition()); 1628 biggestPosition = aii; 1629 } 1630 } 1631 1632 if (getCacheDataToDisk() && anyRelative 1633 && (biggestPosition != null)) { 1634 biggestPosition.setRequestType(AddeImageInfo.REQ_IMAGEDIR); 1635 AreaDirectoryList adl = 1636 new AreaDirectoryList(biggestPosition.getURLString()); 1637 biggestPosition.setRequestType(AddeImageInfo.REQ_IMAGEDATA); 1638 currentDirs = adl.getSortedDirs(); 1639 } else { 1640 currentDirs = null; 1641 } 1642 1643 ThreadManager threadManager = 1644 new ThreadManager("image data reading"); 1645 final ImageSequenceManager sequenceManager = 1646 new ImageSequenceManager(); 1647 int cnt = 1; 1648 DataChoice parent = dataChoice.getParent(); 1649 final List<SingleBandedImage> images = 1650 new ArrayList<SingleBandedImage>(); 1651 MathType rangeType = null; 1652 for (Iterator iter = 1653 descriptorsToUse.iterator(); iter.hasNext(); ) { 1654 final AddeImageDescriptor aid = 1655 (AddeImageDescriptor) iter.next(); 1656 if (currentDirs != null) { 1657 int idx = 1658 Math.abs(aid.getImageInfo().getDatasetPosition()); 1659 if (idx >= currentDirs.length) { 1660 continue; 1661 } 1662 } 1663 1664 String label = ""; 1665 if (parent != null) { 1666 label = label + parent.toString() + ' '; 1667 } else { 1668 DataCategory displayCategory = 1669 dataChoice.getDisplayCategory(); 1670 if (displayCategory != null) { 1671 label = label + displayCategory + ' '; 1672 } 1673 } 1674 label = label + dataChoice.toString(); 1675 final String readLabel = "Time: " + (cnt++) + '/' 1676 + descriptorsToUse.size() + ' ' 1677 + label; 1678 1679 String src = aid.getSource(); 1680 if (!isFromFile(aid)) { 1681 try { 1682 src = replaceKey(src, LINELE_KEY, (Object)("1 1")); 1683 String sizeString = "10 10"; 1684 src = replaceKey(src, SIZE_KEY, (Object)(sizeString)); 1685 String name = dataChoice.getName(); 1686 int idx = name.lastIndexOf('_'); 1687 String unit = name.substring(idx+1); 1688 if (getKey(src, UNIT_KEY).length() == 0) { 1689 src = replaceKey(src, UNIT_KEY, (Object)(unit)); 1690 } 1691 int lSize = numLines; 1692 int eSize = numEles; 1693 sizeString = lSize + " " + eSize; 1694 src = replaceKey(src, SIZE_KEY, (Object)(sizeString)); 1695 src = replaceKey(src, MAG_KEY, (Object)(this.lineMag + " " + this.elementMag)); 1696 aid.setSource(src); 1697 } catch (Exception exc) { 1698 super.makeImageSequence(dataChoice, subset); 1699 } 1700 } 1701 1702 SingleBandedImage image = makeImage(aid, rangeType, true, 1703 readLabel, subset); 1704 if (image != null) { 1705 if(rangeType==null) { 1706 rangeType = ((FunctionType) image.getType()).getRange(); 1707 } 1708 synchronized (images) { 1709 images.add(image); 1710 } 1711 } 1712 } 1713 1714 TreeMap imageMap = new TreeMap(); 1715 for (SingleBandedImage image : images) { 1716 imageMap.put(image.getStartTime(), image); 1717 } 1718 List<SingleBandedImage> sortedImages = 1719 (List<SingleBandedImage>) new ArrayList(imageMap.values()); 1720 if ((sortedImages.size() > 0) 1721 && (sortedImages.get(0) instanceof AreaImageFlatField)) { 1722 DataRange[] sampleRanges = null; 1723 Set domainSet = null; 1724 for (SingleBandedImage sbi : sortedImages) { 1725 AreaImageFlatField aiff = (AreaImageFlatField) sbi; 1726 sampleRanges = aiff.getRanges(true); 1727 if (domainSet == null) { 1728 domainSet = aiff.getDomainSet(); 1729 } 1730 if ((sampleRanges != null) && (sampleRanges.length > 0)) { 1731 for (int rangeIdx = 0; rangeIdx < sampleRanges.length; 1732 rangeIdx++) { 1733 DataRange r = sampleRanges[rangeIdx]; 1734 if (Double.isInfinite(r.getMin()) 1735 || Double.isInfinite(r.getMax())) { 1736 sampleRanges = null; 1737 break; 1738 } 1739 } 1740 } 1741 if (sampleRanges != null) { 1742 break; 1743 } 1744 } 1745 1746 if (sampleRanges != null) { 1747 for (SingleBandedImage sbi : sortedImages) { 1748 AreaImageFlatField aiff = (AreaImageFlatField) sbi; 1749 aiff.setSampleRanges(sampleRanges); 1750 aiff.setDomainIfNeeded(domainSet); 1751 } 1752 } 1753 } 1754 1755 SingleBandedImage[] imageArray = 1756 (SingleBandedImage[]) sortedImages.toArray( 1757 new SingleBandedImage[sortedImages.size()]); 1758 FunctionType imageFunction = 1759 (FunctionType) imageArray[0].getType(); 1760 FunctionType ftype = new FunctionType(RealType.Time, 1761 imageFunction); 1762 return new ImageSequenceImpl(ftype, imageArray); 1763 } catch (Exception exc) { 1764 throw new ucar.unidata.util.WrapperException(exc); 1765 } 1766 1767 } 1768 1769 /** 1770 * Create the single image defined by the given {@link ucar.unidata.data.imagery.AddeImageDescriptor AddeImageDescriptor}. 1771 * 1772 * @param aid Holds image directory and location of the desired image. 1773 * @param rangeType {@literal "rangeType"} to use (if non-{@code null}). 1774 * @param fromSequence _more_ 1775 * @param readLabel 1776 * @param subset geographical subsetting info 1777 * 1778 * @return The data. 1779 * 1780 * @throws RemoteException Java RMI problem 1781 * @throws VisADException VisAD problem 1782 */ 1783 private SingleBandedImage makeImage(AddeImageDescriptor aid, 1784 MathType rangeType, 1785 boolean fromSequence, 1786 String readLabel, DataSelection subset) 1787 throws VisADException, RemoteException { 1788 1789 if (aid == null) { 1790 return null; 1791 } 1792 1793 logger.trace("incoming src={} readLabel={}", aid.getSource(), readLabel); 1794 String src = aid.getSource(); 1795 1796 Hashtable props = subset.getProperties(); 1797 // it only makes sense to set the following properties for things 1798 // coming from an ADDE server 1799 if (!isFromFile(aid)) { 1800 if (props.containsKey("PLACE")) { 1801 src = replaceKey(src, "PLACE", props.get("PLACE")); 1802 } 1803 if (props.containsKey("LATLON")) { 1804 src = replaceKey(src, "LINELE", "LATLON", props.get("LATLON")); 1805 } 1806 if (props.containsKey("LINELE")) { 1807 src = removeKey(src, "LATLON"); 1808 src = replaceKey(src, "LINELE", props.get("LINELE")); 1809 } 1810 if (props.containsKey("MAG")) { 1811 src = replaceKey(src, "MAG", props.get("MAG")); 1812 } 1813 } 1814 aid.setSource(src); 1815 1816 SingleBandedImage result; 1817 result = (SingleBandedImage)getCache(src); 1818 if (result != null) { 1819 setDisplaySource(src, props); 1820 return result; 1821 } 1822 1823 //For now handle non adde urls here 1824 try { 1825 AddeImageInfo aii = aid.getImageInfo(); 1826 AreaDirectory areaDir = null; 1827 try { 1828 if (aii != null) { 1829 logger.trace("imageinfo={}", aii.toString()); 1830 if (currentDirs != null) { 1831 int pos = Math.abs(aii.getDatasetPosition()); 1832 int band = 0; 1833 String bandString = aii.getBand(); 1834 if ((bandString != null) && !aii.ALL.equals(bandString)) { 1835 band = new Integer(bandString).intValue(); 1836 } 1837 // TODO: even though the band is non-zero we might only 1838 // get back one band 1839 band = 0; 1840 areaDir = currentDirs[currentDirs.length - pos - 1][band]; 1841 } else { 1842 // If its absolute time then just use the AD from the descriptor 1843 if ((aii.getStartDate() != null) || (aii.getEndDate() != null)) { 1844 areaDir = aid.getDirectory(); 1845 } else { 1846 } 1847 } 1848 } else { 1849 logger.trace("uh oh"); 1850 } 1851 } catch (Exception exc) { 1852 LogUtil.printMessage("error looking up area dir"); 1853 logger.error("error looking up area dir", exc); 1854 return null; 1855 } 1856 1857 if (areaDir == null) { 1858 areaDir = aid.getDirectory(); 1859 } 1860 1861 if (!getCacheDataToDisk()) { 1862 areaDir = null; 1863 } 1864 1865 if (!fromSequence || (aid.getIsRelative() && (currentDirs == null))) { 1866 areaDir = null; 1867 } 1868 1869 if (areaDir != null) { 1870 if (isFromFile(aid)) { 1871 int hash = ((aii != null) 1872 ? aii.getURLString().hashCode() 1873 : areaDir.hashCode()); 1874 if (rangeType == null) { 1875 result = AreaImageFlatField.createImmediate(aid, readLabel); 1876 } else { 1877 //Else, pass in the already created range type 1878 result = AreaImageFlatField.create(aid, areaDir, rangeType, readLabel); 1879 } 1880 } 1881 1882 } else { 1883 src = aid.getSource(); 1884 try { 1885 savePlace = this.laLoSel.getPlace(); 1886 saveLat = this.laLoSel.getLatitude(); 1887 saveLon = this.laLoSel.getLongitude(); 1888 saveNumLine = this.laLoSel.getNumLines(); 1889 saveNumEle = this.laLoSel.getNumEles(); 1890 saveLineMag = this.laLoSel.getLineMag(); 1891 saveEleMag = this.laLoSel.getElementMag(); 1892 } catch (Exception e) { 1893 logger.error("error reading from laLoSel", e); 1894 // savePlace = getSavePlace(); 1895 // this.laLoSel.setPlace(savePlace); 1896 // saveLat = getSaveLat(); 1897 // this.laLoSel.setLatitude(saveLat); 1898 // saveLon = getSaveLon(); 1899 // this.laLoSel.setLongitude(saveLon); 1900 // saveNumLine = getSaveNumLine(); 1901 // this.laLoSel.setNumLines(saveNumLine); 1902 // saveNumEle = getSaveNumEle(); 1903 // this.laLoSel.setNumEles(saveNumEle); 1904 // saveLineMag = getSaveLineMag(); 1905 // this.laLoSel.setLineMag(saveLineMag); 1906 // saveEleMag = getSaveEleMag(); 1907 // this.laLoSel.setElementMag(saveEleMag); 1908 this.laLoSel.setPlace(savePlace); 1909 this.laLoSel.setLatitude(saveLat); 1910 this.laLoSel.setLongitude(saveLon); 1911 this.laLoSel.setNumLines(saveNumLine); 1912 this.laLoSel.setNumEles(saveNumEle); 1913 this.laLoSel.setLineMag(saveLineMag); 1914 this.laLoSel.setElementMag(saveEleMag); 1915 } 1916 1917 src = replaceKey(src, PLACE_KEY, savePlace); 1918 src = removeKey(src, LINELE_KEY); 1919 if (getKey(src, LATLON_KEY).length() != 0) { 1920 String latStr = Double.toString(saveLat); 1921 if (latStr.length() > 8) { 1922 latStr = latStr.substring(0,7); 1923 } 1924 String lonStr = Double.toString(saveLon); 1925 if (lonStr.length() > 9) { 1926 lonStr = lonStr.substring(0,8); 1927 } 1928 src = replaceKey(src, LATLON_KEY, latStr + ' ' + lonStr); 1929 } 1930 src = replaceKey(src, SIZE_KEY, saveNumLine + ' ' + saveNumEle); 1931 src = replaceKey(src, MAG_KEY, saveLineMag + ' ' + saveEleMag); 1932 } 1933 1934 logger.trace("Getting a new aa: ", src); 1935 AreaAdapter aa = new AreaAdapter(src, false); 1936 areaDir = previewDir; 1937 result = aa.getImage(); 1938 1939 putCache(src, result); 1940 aid.setSource(src); 1941 iml.add(aid); 1942 setImageList(iml); 1943 setDisplaySource(src, props); 1944 return result; 1945 1946 } catch (java.io.IOException ioe) { 1947 throw new VisADException("Creating AreaAdapter - " + ioe); 1948 } 1949 } 1950 1951 /** 1952 * Make a parmeter name for the BandInfo 1953 * 1954 * @param bi the BandInfo in question 1955 * 1956 * @return a name for the parameter 1957 */ 1958 private static String makeBandParam(BandInfo bi) { 1959 return new StringBuilder() 1960 .append(bi.getSensor()) 1961 .append("_Band") 1962 .append(bi.getBandNumber()) 1963 .append('_') 1964 .append(bi.getPreferredUnit()).toString(); 1965 } 1966 1967 private static String makeBandParam(AddeImageDescriptor descriptor) { 1968 AreaDirectory areaDir = descriptor.getDirectory(); 1969 if (areaDir == null) { 1970 throw new NullPointerException("No AREA directory!"); 1971 } 1972 return new StringBuilder() 1973 .append(areaDir.getSensorID()) 1974 .append("_Band") 1975 .append(areaDir.getBands()[0]) 1976 .append('_') 1977 .append(areaDir.getCalibrationType()).toString(); 1978 } 1979 1980 /** 1981 * Get the object that we use to display relative time. Relative time is defined 1982 * using an integer index, 0...n. We don't want to show the actual integer. 1983 * Rather we want to show "Third most recent", "Fourth most recent", etc. 1984 * 1985 * @param aid The image descriptor 1986 * @return The object that represents the relative time index of the aid 1987 */ 1988 private Object getRelativeTimeObject(AddeImageDescriptor aid) { 1989 return new TwoFacedObject(aid.toString(), 1990 new Integer(aid.getRelativeIndex())); 1991 } 1992 1993 /** 1994 * Sort the list of data choices on their time 1995 * 1996 * @param choices The data choices 1997 * 1998 * @return The data choices sorted 1999 */ 2000 private List sortChoices(List choices) { 2001 Object[] choicesArray = choices.toArray(); 2002 Comparator comp = new Comparator() { 2003 public int compare(Object o1, Object o2) { 2004 AddeImageDescriptor aid1 = getDescriptor(o1); 2005 AddeImageDescriptor aid2 = getDescriptor(o2); 2006 if ((aid1 == null) || (aid2 == null)) { 2007 return -1; 2008 } 2009 if (aid1.getIsRelative()) { 2010 if (aid1.getRelativeIndex() < aid2.getRelativeIndex()) { 2011 return 0; 2012 } else if (aid1.getRelativeIndex() 2013 == aid2.getRelativeIndex()) { 2014 return 1; 2015 } 2016 return -1; 2017 } 2018 return aid1.getImageTime().compareTo(aid2.getImageTime()); 2019 } 2020 }; 2021 Arrays.sort(choicesArray, comp); 2022 return new ArrayList(Arrays.asList(choicesArray)); 2023 2024 } 2025 2026 /** 2027 * Get a list of descriptors from the choice and subset 2028 * 2029 * @param dataChoice Data choice 2030 * @param subset subsetting info 2031 * 2032 * @return list of descriptors matching the selection 2033 */ 2034 public List getDescriptors(DataChoice dataChoice, DataSelection subset) { 2035 // logger.trace("choice={} subset props={} geo={}", new Object[] { dataChoice, subset.getProperties(), subset.getGeoSelection() }); 2036 int linRes = this.lineResolution; 2037 int eleRes = this.elementResolution; 2038 int newLinRes = linRes; 2039 int newEleRes = eleRes; 2040 List times = getTimesFromDataSelection(subset, dataChoice); 2041 // if (dataChoice.getDataSelection() == null) { 2042 // logger.trace("setting datasel!"); 2043 // dataChoice.setDataSelection(subset); 2044 // } 2045 if ((times == null) || times.isEmpty()) { 2046 times = imageTimes; 2047 } 2048 List descriptors = new ArrayList(); 2049 Object choiceId = dataChoice.getId(); 2050 // if (choiceId instanceof BandInfo) { 2051 // 2052 // } 2053 int choiceBandNum = ((BandInfo)dataChoice.getId()).getBandNumber(); 2054 int choiceSensorId = ((BandInfo)dataChoice.getId()).getSensor(); 2055 String choicePrefUnit = ((BandInfo)dataChoice.getId()).getPreferredUnit(); 2056 for (Iterator iter = times.iterator(); iter.hasNext(); ) { 2057 Object time = iter.next(); 2058 AddeImageDescriptor found = null; 2059 AddeImageDescriptor foundTimeMatch = null; 2060 if (saveImageList.isEmpty()) { 2061 saveImageList = getImageList(); 2062 } 2063 for (Iterator iter2 = saveImageList.iterator(); iter2.hasNext(); ) { 2064 AddeImageDescriptor aid = getDescriptor(iter2.next()); 2065 if (aid != null) { 2066 if (aid.getIsRelative()) { 2067 Object id; 2068 if (time instanceof TwoFacedObject) { 2069 id = ((TwoFacedObject)time).getId(); 2070 } else { 2071 id = time; 2072 } 2073 if ((id instanceof Integer) && ((Integer)id).intValue() == aid.getRelativeIndex()) { 2074 found = aid; 2075 break; 2076 } 2077 } else { 2078 int aidBand = aid.getDirectory().getBands()[0]; 2079 int aidSensorId = aid.getDirectory().getSensorID(); 2080 String calType = aid.getDirectory().getCalibrationType(); 2081 if (foundTimeMatch == null && aid.getImageTime().equals(time)) { 2082 logger.trace("found time match {}", time); 2083 foundTimeMatch = aid; 2084 } 2085 if (aid.getImageTime().equals(time) && choiceBandNum == aidBand && choiceSensorId == aidSensorId && choicePrefUnit.equals(calType)) { 2086 // the problem is here! 2087 logger.trace("found aid={} src={}", makeBandParam(aid), aid.getSource()); 2088 logger.trace("target info: param={}", dataChoice.getName()); 2089 found = aid; 2090 break; 2091 } 2092 } 2093 } 2094 } 2095 2096 if (found == null && foundTimeMatch != null) { 2097 logger.trace("good enough!?"); 2098 found = foundTimeMatch; 2099 } 2100 2101 if (found != null) { 2102 try { 2103 AddeImageDescriptor desc = new AddeImageDescriptor(found); 2104 //Sometimes we might have a null imageinfo 2105 if(desc.getImageInfo()!=null) { 2106 AddeImageInfo aii = 2107 (AddeImageInfo) desc.getImageInfo().clone(); 2108 BandInfo bi = (BandInfo) dataChoice.getId(); 2109 List<BandInfo> bandInfos = 2110 (List<BandInfo>) getProperty(PROP_BANDINFO, (Object) null); 2111 boolean hasBand = true; 2112 //If this data source has been changed after we have create a display 2113 //then the possibility exists that the bandinfo contained by the incoming 2114 //data choice might not be valid. If it isn't then default to the first 2115 //one in the list 2116 if(bandInfos != null) { 2117 hasBand = bandInfos.contains(bi); 2118 if(!hasBand) { 2119 } 2120 if(!hasBand && bandInfos.size() > 0) { 2121 bi = bandInfos.get(0); 2122 } else { 2123 //Not sure what to do here. 2124 } 2125 } 2126 aii.setBand("" + bi.getBandNumber()); 2127 aii.setPlaceValue("ULEFT"); 2128 2129 try { 2130 AddeImageDescriptor newAid = new AddeImageDescriptor(aii.getURLString()); 2131 AreaDirectory newAd = newAid.getDirectory(); 2132 newLinRes = newAd.getValue(11); 2133 newEleRes = newAd.getValue(12); 2134 } catch (Exception e) { 2135 logger.error("resetting resolution", e); 2136 } 2137 2138 double[][] projCoords = new double[2][2]; 2139 try { 2140 AreaDirectory ad = desc.getDirectory(); 2141 double lin = (double)ad.getValue(5); 2142 double ele = (double)ad.getValue(6); 2143 aii.setLocateKey("LINELE"); 2144 aii.setLocateValue((int)lin + " " + (int)ele); 2145 projCoords[0][0] = lin; 2146 projCoords[1][0] = ele; 2147 lin += (double)ad.getValue(8); 2148 ele += (double)ad.getValue(9); 2149 projCoords[0][1] = lin; 2150 projCoords[1][1] = ele; 2151 } catch (Exception e) { 2152 logger.error("problem with adjusting projCoords?", e); 2153 return descriptors; 2154 } 2155 int lins = Math.abs((int)(projCoords[1][1] - projCoords[1][0])); 2156 int eles = Math.abs((int)(projCoords[0][1] - projCoords[0][0])); 2157 lins = lins*linRes/newLinRes; 2158 if (this.lineMag > 0) { 2159 lins *= this.lineMag; 2160 } else { 2161 lins /= -this.lineMag; 2162 } 2163 2164 eles = eles*eleRes/newEleRes; 2165 2166 if (elementMag > 0) { 2167 eles *= elementMag; 2168 } else { 2169 eles /= -elementMag; 2170 } 2171 2172 aii.setLines(lins); 2173 aii.setElements(eles); 2174 desc.setImageInfo(aii); 2175 desc.setSource(aii.getURLString()); 2176 } 2177 descriptors.add(desc); 2178 } catch (CloneNotSupportedException cnse) {} 2179 } 2180 } 2181 return descriptors; 2182 } 2183 2184 /** 2185 * Get the subset of the composite based on the selection 2186 * 2187 * @param choice composite choice 2188 * @param subset time selection 2189 * 2190 * @return subset list 2191 */ 2192 private List getChoicesFromSubset(CompositeDataChoice choice, 2193 DataSelection subset) { 2194 List choices = choice.getDataChoices(); 2195 if (subset == null) { 2196 return choices; 2197 } 2198 List times = subset.getTimes(); 2199 if (times == null) { 2200 return choices; 2201 } 2202 times = TwoFacedObject.getIdList(times); 2203 List subChoices = new ArrayList(); 2204 Object firstTime = times.get(0); 2205 if (firstTime instanceof Integer) { 2206 for (Iterator iter = times.iterator(); iter.hasNext(); ) { 2207 subChoices.add( 2208 choices.get(((Integer) iter.next()).intValue())); 2209 } 2210 } else { // TODO: what if they are DateTimes? 2211 subChoices.addAll(choices); 2212 } 2213 return subChoices; 2214 } 2215 2216 private AreaDirectory getPreviewDirectory(AddeImageDescriptor aid) { 2217 AreaDirectory directory = aid.getDirectory(); 2218 int times = imageTimes.size(); 2219 if (times == 1) return directory; 2220 String src = aid.getSource(); 2221 2222 src = removeKey(src, LATLON_KEY); 2223 src = removeKey(src, LINELE_KEY); 2224 src = removeKey(src, PLACE_KEY); 2225 src = removeKey(src, SIZE_KEY); 2226 src = removeKey(src, UNIT_KEY); 2227 src = removeKey(src, MAG_KEY); 2228 src = removeKey(src, SPAC_KEY); 2229 src = removeKey(src, NAV_KEY); 2230 src = removeKey(src, AUX_KEY); 2231 src = removeKey(src, DOC_KEY); 2232 2233 int maxLine = 0; 2234 int maxEle = 0; 2235 int imageSize = 0; 2236 src = src.replace("imagedata", "imagedir"); 2237 boolean isRelative = aid.getIsRelative(); 2238 for (int i=0; i<times; i++) { 2239 if (isRelative) { 2240 src = replaceKey(src, "POS", new Integer(i).toString()); 2241 } else { 2242 DateTime dt = (DateTime)imageTimes.get(i); 2243 String timeStr = dt.timeString(); 2244 timeStr = timeStr.replace("Z", " "); 2245 src = removeKey(src, "POS"); 2246 src = replaceKey(src, "TIME", timeStr + timeStr + "I"); 2247 } 2248 try { 2249 AreaDirectoryList dirList = new AreaDirectoryList(src); 2250 List ad = dirList.getDirs(); 2251 AreaDirectory areaDir = (AreaDirectory)ad.get(0); 2252 int lines = areaDir.getLines(); 2253 int eles = areaDir.getElements(); 2254 if (imageSize < lines*eles) { 2255 imageSize = lines * eles; 2256 maxLine = lines; 2257 maxEle = eles; 2258 directory = areaDir; 2259 } 2260 } catch (Exception e) { 2261 logger.error("problem when dealing with AREA directory", e); 2262 } 2263 } 2264 2265 return directory; 2266 } 2267 2268 private String getServer(String urlString) { 2269 int ix = urlString.indexOf("//") + 2; 2270 String temp = urlString.substring(ix); 2271 ix = temp.indexOf("/"); 2272 String retStr = temp.substring(0, ix); 2273 return retStr; 2274 } 2275 2276 public void setDisplaySource(String src, Hashtable props) { 2277 if (!props.isEmpty()) { 2278 Enumeration propEnum = props.keys(); 2279 for (int i=0; propEnum.hasMoreElements(); i++) { 2280 String key = propEnum.nextElement().toString(); 2281 Object val = props.get(key); 2282 if (getKey(src, key).length() != 0) { 2283 src = replaceKey(src, key, val); 2284 } 2285 } 2286 } 2287 this.displaySource = src; 2288 String unit = getKey(src, UNIT_KEY); 2289 if (unit.length() != 0) { 2290 sourceProps.put(UNIT_KEY.toUpperCase(), unit); 2291 } 2292 } 2293 2294 public String getDisplaySource() { 2295 return this.displaySource; 2296 } 2297 2298 2299 private float[] getLineEleResolution(AreaDirectory ad) { 2300 logger.trace("ad: {} sensor: {}", ad, ad.getSensorID()); 2301 float[] res = {(float)1.0, (float)1.0}; 2302 int sensor = ad.getSensorID(); 2303 List lines = null; 2304 try { 2305 String buff = getUrl(); 2306 2307 lines = readTextLines(buff); 2308 if (lines == null) { 2309 return res; 2310 } 2311 2312 int gotit = -1; 2313 String[] cards = StringUtil.listToStringArray(lines); 2314 logger.trace("cards: {}", cards); 2315 2316 for (int i=0; i<cards.length; i++) { 2317 if ( ! cards[i].startsWith("Sat ")) continue; 2318 StringTokenizer st = new StringTokenizer(cards[i]," "); 2319 String temp = st.nextToken(); // throw away the key 2320 int m = st.countTokens(); 2321 for (int k=0; k<m; k++) { 2322 int ss = Integer.parseInt(st.nextToken().trim()); 2323 if (ss == sensor) { 2324 gotit = i; 2325 break; 2326 } 2327 } 2328 2329 if (gotit != -1) { 2330 break; 2331 } 2332 } 2333 2334 if (gotit == -1) { 2335 return res; 2336 } 2337 2338 int gotSrc = -1; 2339 for (int i=gotit; i<cards.length; i++) { 2340 if (cards[i].startsWith("EndSat")) { 2341 return res; 2342 } 2343 if (!cards[i].startsWith("B") ) { 2344 continue; 2345 } 2346 StringTokenizer tok = new StringTokenizer(cards[i]); 2347 String str = tok.nextToken(); 2348 str = tok.nextToken(); 2349 Float flt = new Float(str); 2350 res[0] = flt.floatValue(); 2351 str = tok.nextToken(); 2352 flt = new Float(str); 2353 res[1] = flt.floatValue(); 2354 return res; 2355 } 2356 } catch (Exception e) { 2357 logger.error("problem getting the line+element rez", e); 2358 } 2359 return res; 2360 } 2361 2362 2363 /** 2364 * Read the adde text url and return the lines of text. 2365 * If unsuccessful return null. 2366 * 2367 * @param url adde url to a text file 2368 * 2369 * @return List of lines or {@code null} if in error. 2370 */ 2371 protected List readTextLines(String url) { 2372 AddeTextReader reader = new AddeTextReader(url); 2373 List lines = null; 2374 if ("OK".equals(reader.getStatus())) { 2375 lines = reader.getLinesOfText(); 2376 } 2377 return lines; 2378 } 2379 2380 /** 2381 * Create the first part of the ADDE request URL 2382 * 2383 * @param requestType type of request 2384 * @return ADDE URL prefix 2385 */ 2386 protected String getUrl() { 2387 String str = source; 2388 str = str.replaceFirst("imagedata", "text"); 2389 int indx = str.indexOf("VERSION"); 2390 str = str.substring(0, indx); 2391 str = str.concat("file=SATBAND"); 2392 return str; 2393 } 2394 2395 public Hashtable getSourceProps() { 2396 return this.sourceProps; 2397 } 2398 2399 public void setSourceProps(Hashtable sourceProps) { 2400 this.sourceProps = sourceProps; 2401 } 2402 2403 // public MapProjection getSampleMapProjection() { 2404 // return this.sampleMapProjection; 2405 // } 2406 // 2407 // public void setSampleMapProjection(MapProjection sampleMapProjection) { 2408 // this.sampleMapProjection = sampleMapProjection; 2409 // } 2410 2411 public String getChoiceName() { 2412 return this.choiceName; 2413 } 2414 2415 public void setChoiceName(String choiceName) { 2416 this.choiceName = choiceName; 2417 } 2418 2419 // public MapProjection getPreviewProjection() { 2420 // return this.previewProjection; 2421 // } 2422 // 2423 // public void setPreviewProjection(MapProjection previewProjection) { 2424 // this.previewProjection = previewProjection; 2425 // } 2426 // 2427 // public AreaDirectory getPreviewDir() { 2428 // return this.previewDir; 2429 // } 2430 // 2431 // public void setPreviewDir(AreaDirectory previewDir) { 2432 // this.previewDir = previewDir; 2433 // } 2434 2435 public String getSavePlace() { 2436 return this.savePlace; 2437 } 2438 2439 public void setSavePlace(String savePlace) { 2440 this.savePlace = savePlace; 2441 } 2442 2443 public double getSaveLat() { 2444 return this.saveLat; 2445 } 2446 2447 public void setSaveLat(double saveLat) { 2448 this.saveLat = saveLat; 2449 } 2450 2451 public double getSaveLon() { 2452 return this.saveLon; 2453 } 2454 2455 public void setSaveLon(double saveLon) { 2456 this.saveLon = saveLon; 2457 } 2458 2459 public int getSaveNumLine() { 2460 return this.saveNumLine; 2461 } 2462 2463 public void setSaveNumLine(int saveNumLine) { 2464 this.saveNumLine = saveNumLine; 2465 } 2466 2467 public int getSaveNumEle() { 2468 return this.saveNumEle; 2469 } 2470 2471 public void setSaveNumEle(int saveNumEle) { 2472 this.saveNumEle = saveNumEle; 2473 } 2474 2475 public int getSaveLineMag() { 2476 return this.saveLineMag; 2477 } 2478 2479 public void setSaveLineMag(int saveLineMag) { 2480 this.saveLineMag = saveLineMag; 2481 } 2482 2483 public int getSaveEleMag() { 2484 return this.saveEleMag; 2485 } 2486 2487 public void setSaveEleMag(int saveEleMag) { 2488 this.saveEleMag = saveEleMag; 2489 } 2490 2491 public String getSource() { 2492 return this.source; 2493 } 2494 2495 public void setSource(String source) { 2496 this.source = source; 2497 } 2498 2499 public boolean getShowPreview() { 2500 return this.showPreview; 2501 } 2502 2503 public void setShowPreview(boolean showPreview) { 2504 this.showPreview = showPreview; 2505 } 2506 2507 public boolean getSaveShowPreview() { 2508 return this.saveShowPreview; 2509 } 2510 2511 public void setSaveShowPreview(boolean saveShowPreview) { 2512 this.saveShowPreview = saveShowPreview; 2513 } 2514 2515 private void getSaveComponents() { 2516 saveCoordType = this.laLoSel.getCoordinateType(); 2517 savePlace = this.laLoSel.getPlace(); 2518 if (saveCoordType.equals(this.laLoSel.getLatLonType())) { 2519 saveLat = this.laLoSel.getLatitude(); 2520 saveLon = this.laLoSel.getLongitude(); 2521 } 2522 saveNumLine = this.laLoSel.getNumLines(); 2523 saveNumEle = this.laLoSel.getNumEles(); 2524 saveLineMag = this.laLoSel.getLineMag(); 2525 saveEleMag = this.laLoSel.getElementMag(); 2526 } 2527 2528 public static class BundlePreviewSelection extends DataSelectionComponent { 2529 final String label; 2530 public BundlePreviewSelection(final String label) { 2531 super(label); 2532 this.label = label; 2533 } 2534 2535 @Override protected JComponent doMakeContents() { 2536 // TODO Auto-generated method stub 2537 JPanel panel = new JPanel(); 2538 panel.setLayout(new BoxLayout(panel, BoxLayout.Y_AXIS)); 2539 JLabel label1 = new JLabel("Area coverage has been defined by the data bundle;"); 2540 JLabel label2 = new JLabel("further subsetting is not currently supported."); 2541 label1.setAlignmentX(Component.CENTER_ALIGNMENT); 2542 label2.setAlignmentX(Container.CENTER_ALIGNMENT); 2543 panel.add(label1); 2544 panel.add(label2); 2545 return panel; 2546 } 2547 2548 @Override public void applyToDataSelection(DataSelection dataSelection) { 2549 } 2550 2551 /** 2552 * Overridden to disable these dummy tabs from showing up in properties 2553 * dialog. 2554 */ 2555 @Override public boolean getShowInControlProperties() { 2556 return false; 2557 } 2558 } 2559 }