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.data.hydra; 029 030import java.io.File; 031import java.rmi.RemoteException; 032import java.util.Enumeration; 033import java.util.HashMap; 034import java.util.Hashtable; 035import java.util.List; 036import java.util.Map; 037 038import javax.swing.JOptionPane; 039 040import org.slf4j.Logger; 041import org.slf4j.LoggerFactory; 042 043import ucar.nc2.NetcdfFile; 044import ucar.nc2.Variable; 045import ucar.unidata.data.DataCategory; 046import ucar.unidata.data.DataChoice; 047import ucar.unidata.data.DataSelection; 048import ucar.unidata.data.DataSelectionComponent; 049import ucar.unidata.data.DataSourceDescriptor; 050import ucar.unidata.data.DirectDataChoice; 051import ucar.unidata.data.GeoLocationInfo; 052import ucar.unidata.data.GeoSelection; 053import ucar.unidata.util.Misc; 054 055import visad.Data; 056import visad.FlatField; 057import visad.GriddedSet; 058import visad.VisADException; 059 060import edu.wisc.ssec.mcidasv.data.HydraDataSource; 061import edu.wisc.ssec.mcidasv.data.PreviewSelection; 062 063/** 064 * A data source for Multi Dimension Data 065 */ 066 067public class MultiDimensionDataSource extends HydraDataSource { 068 069 private static final Logger logger = LoggerFactory.getLogger(MultiDimensionDataSource.class); 070 071 /** Sources file */ 072 protected String filename; 073 074 protected MultiDimensionReader reader; 075 076 protected MultiDimensionAdapter[] adapters = null; 077 protected Map[] defaultSubsets = null; 078 private Map<String, MultiDimensionAdapter> adapterMap = new HashMap<>(); 079 protected Hashtable[] propsArray = null; 080 protected List[] categoriesArray = null; 081 082 protected SpectrumAdapter spectrumAdapter; 083 084 private static final String DATA_DESCRIPTION = "Multi Dimension Data"; 085 086 private Map<String, double[]> defaultSubset; 087 public TrackAdapter track_adapter; 088 private MultiSpectralData multiSpectData; 089 090 private List categories; 091 private boolean hasImagePreview = false; 092 private boolean hasTrackPreview = false; 093 094 private TrackSelection trackSelection = null; 095 096 /** 097 * Zero-argument constructor for construction via unpersistence. 098 */ 099 public MultiDimensionDataSource() {} 100 101 /** 102 * Construct a new HYDRA hdf data source. 103 * @param descriptor descriptor for this {@code DataSource} 104 * @param fileName name of the hdf file to read 105 * @param properties hashtable of properties 106 * 107 * @throws VisADException problem creating data 108 */ 109 public MultiDimensionDataSource(DataSourceDescriptor descriptor, 110 String fileName, Hashtable properties) 111 throws VisADException { 112 this(descriptor, Misc.newList(fileName), properties); 113 } 114 115 /** 116 * Construct a new HYDRA hdf data source. 117 * @param descriptor descriptor for this {@code DataSource} 118 * @param newSources List of filenames 119 * @param properties hashtable of properties 120 * 121 * @throws VisADException problem creating data 122 */ 123 public MultiDimensionDataSource(DataSourceDescriptor descriptor, 124 List newSources, Hashtable properties) 125 throws VisADException { 126 super(descriptor, newSources, DATA_DESCRIPTION, properties); 127 128 this.filename = (String) sources.get(0); 129 130 try { 131 setup(); 132 } catch (Exception e) { 133 throw new VisADException("could not set up MultiDimensionDataSource", e); 134 } 135 } 136 137 public void setup() throws Exception { 138 139 try { 140 if (filename.contains("MYD02SSH")) { // get file union 141 String other = (String) sources.get(1); 142 if (filename.endsWith("nav.hdf")) { 143 String tmp = filename; 144 filename = other; 145 other = tmp; 146 } 147 reader = NetCDFFile.makeUnion(filename, other); 148 } 149 else { 150 reader = new NetCDFFile(filename); 151 } 152 } catch (Exception e) { 153 logger.error("Cannot create NetCDF reader for file: " + filename, e); 154 } 155 156 adapters = new MultiDimensionAdapter[2]; 157 defaultSubsets = new HashMap[2]; 158 Hashtable<String, String[]> properties = new Hashtable<>(); 159 160 String name = (new File(filename)).getName(); 161 162 if (name.startsWith("MOD04") || name.startsWith("MYD04")) { 163 Map<String, Object> table = SwathAdapter.getEmptyMetadataTable(); 164 table.put("array_name", "mod04/Data_Fields/Optical_Depth_Land_And_Ocean"); 165 table.put("lon_array_name", "mod04/Geolocation_Fields/Longitude"); 166 table.put("lat_array_name", "mod04/Geolocation_Fields/Latitude"); 167 table.put("XTrack", "Cell_Across_Swath"); 168 table.put("Track", "Cell_Along_Swath"); 169 table.put("geo_Track", "Cell_Along_Swath"); 170 table.put("geo_XTrack", "Cell_Across_Swath"); 171 table.put("scale_name", "scale_factor"); 172 table.put("offset_name", "add_offset"); 173 table.put("fill_value_name", "_FillValue"); 174 table.put("range_name", "Optical_Depth_Land_And_Ocean"); 175 adapters[0] = new SwathAdapter(reader, table); 176 categories = DataCategory.parseCategories("2D grid;GRID-2D;"); 177 defaultSubset = adapters[0].getDefaultSubset(); 178 defaultSubsets[0] = defaultSubset; 179 hasImagePreview = true; 180 } 181 else if (name.startsWith("MOD06") || name.startsWith("MYD06")) { 182 hasImagePreview = true; 183 String path = "mod06/Data_Fields/"; 184 String[] arrayNames = new String[] {"Cloud_Optical_Thickness", "Cloud_Effective_Radius", "Cloud_Water_Path"}; 185 String[] arrayNames_5km = new String[] {"Cloud_Top_Pressure", "Cloud_Top_Temperature", "Cloud_Fraction"}; 186 187 adapters = new MultiDimensionAdapter[arrayNames.length+arrayNames_5km.length]; 188 defaultSubsets = new HashMap[arrayNames.length+arrayNames_5km.length]; 189 categoriesArray = new List[adapters.length]; 190 191 192 for (int k=0; k<arrayNames.length; k++) { 193 Map<String, Object> table = SwathAdapter.getEmptyMetadataTable(); 194 table.put("array_name", path.concat(arrayNames[k])); 195 table.put("lon_array_name", "mod06/Geolocation_Fields/Longitude"); 196 table.put("lat_array_name", "mod06/Geolocation_Fields/Latitude"); 197 table.put("XTrack", "Cell_Across_Swath_1km"); 198 table.put("Track", "Cell_Along_Swath_1km"); 199 table.put("geo_Track", "Cell_Along_Swath_5km"); 200 table.put("geo_XTrack", "Cell_Across_Swath_5km"); 201 table.put("scale_name", "scale_factor"); 202 table.put("offset_name", "add_offset"); 203 table.put("fill_value_name", "_FillValue"); 204 table.put("range_name", arrayNames[k]); 205 206 table.put(SwathAdapter.geo_track_offset_name, Double.toString(2.0)); 207 table.put(SwathAdapter.geo_xtrack_offset_name, Double.toString(2.0)); 208 table.put(SwathAdapter.geo_track_skip_name, Double.toString(5.0)); 209 table.put(SwathAdapter.geo_xtrack_skip_name, Double.toString(5.0148148148)); 210 211 SwathAdapter swathAdapter = new SwathAdapter(reader, table); 212 swathAdapter.setDefaultStride(10); 213 defaultSubset = swathAdapter.getDefaultSubset(); 214 adapters[k] = swathAdapter; 215 defaultSubsets[k] = defaultSubset; 216 categoriesArray[k] = DataCategory.parseCategories("1km swath;GRID-2D;"); 217 } 218 219 for (int k=0; k<arrayNames_5km.length; k++) { 220 Map<String, Object> table = SwathAdapter.getEmptyMetadataTable(); 221 table.put("array_name", path.concat(arrayNames_5km[k])); 222 table.put("lon_array_name", "mod06/Geolocation_Fields/Longitude"); 223 table.put("lat_array_name", "mod06/Geolocation_Fields/Latitude"); 224 table.put("XTrack", "Cell_Across_Swath_5km"); 225 table.put("Track", "Cell_Along_Swath_5km"); 226 table.put("geo_Track", "Cell_Along_Swath_5km"); 227 table.put("geo_XTrack", "Cell_Across_Swath_5km"); 228 table.put("scale_name", "scale_factor"); 229 table.put("offset_name", "add_offset"); 230 table.put("fill_value_name", "_FillValue"); 231 table.put("range_name", arrayNames_5km[k]); 232 233 SwathAdapter swathAdapter = new SwathAdapter(reader, table); 234 defaultSubset = swathAdapter.getDefaultSubset(); 235 adapters[arrayNames.length+k] = swathAdapter; 236 defaultSubsets[arrayNames.length+k] = defaultSubset; 237 categoriesArray[arrayNames.length+k] = DataCategory.parseCategories("5km swath;GRID-2D;"); 238 } 239 } 240 else if (name.startsWith("a1") && name.contains("mod06")) { 241 hasImagePreview = true; 242 String[] arrayNames = new String[] {"Cloud_Optical_Thickness", "Cloud_Effective_Radius", "Cloud_Water_Path"}; 243 String[] arrayNames_5km = new String[] {"Cloud_Top_Pressure", "Cloud_Top_Temperature", "Cloud_Fraction"}; 244 245 adapters = new MultiDimensionAdapter[arrayNames.length+arrayNames_5km.length]; 246 defaultSubsets = new HashMap[arrayNames.length+arrayNames_5km.length]; 247 categoriesArray = new List[adapters.length]; 248 249 250 for (int k=0; k<arrayNames.length; k++) { 251 Map<String, Object> table = SwathAdapter.getEmptyMetadataTable(); 252 table.put("array_name", arrayNames[k]); 253 table.put("lon_array_name", "Longitude"); 254 table.put("lat_array_name", "Latitude"); 255 table.put("array_dimension_names", new String[] {"Cell_Along_Swath_1km", "Cell_Across_Swath_1km"}); 256 table.put("lon_array_dimension_names", new String[] {"Cell_Along_Swath_1km", "Cell_Across_Swath_1km"}); 257 table.put("lat_array_dimension_names", new String[] {"Cell_Along_Swath_1km", "Cell_Across_Swath_1km"}); 258 table.put("XTrack", "Cell_Across_Swath_1km"); 259 table.put("Track", "Cell_Along_Swath_1km"); 260 table.put("geo_Track", "Cell_Along_Swath_5km"); 261 table.put("geo_XTrack", "Cell_Across_Swath_5km"); 262 table.put("scale_name", "scale_factor"); 263 table.put("offset_name", "add_offset"); 264 table.put("fill_value_name", "_FillValue"); 265 table.put("range_name", arrayNames[k]); 266 267 table.put(SwathAdapter.geo_track_offset_name, Double.toString(2.0)); 268 table.put(SwathAdapter.geo_xtrack_offset_name, Double.toString(2.0)); 269 table.put(SwathAdapter.geo_track_skip_name, Double.toString(5.0)); 270 table.put(SwathAdapter.geo_xtrack_skip_name, Double.toString(5.0148148148)); 271 272 SwathAdapter swathAdapter = new SwathAdapter(reader, table); 273 swathAdapter.setDefaultStride(10); 274 defaultSubset = swathAdapter.getDefaultSubset(); 275 adapters[k] = swathAdapter; 276 defaultSubsets[k] = defaultSubset; 277 categoriesArray[k] = DataCategory.parseCategories("1km swath;GRID-2D;"); 278 } 279 280 for (int k=0; k<arrayNames_5km.length; k++) { 281 Map<String, Object> table = SwathAdapter.getEmptyMetadataTable(); 282 table.put("array_name", arrayNames_5km[k]); 283 table.put("lon_array_name", "Longitude"); 284 table.put("lat_array_name", "Latitude"); 285 table.put("array_dimension_names", new String[] {"Cell_Along_Swath_5km", "Cell_Across_Swath_5km"}); 286 table.put("lon_array_dimension_names", new String[] {"Cell_Along_Swath_5km", "Cell_Across_Swath_5km"}); 287 table.put("lat_array_dimension_names", new String[] {"Cell_Along_Swath_5km", "Cell_Across_Swath_5km"}); 288 table.put("XTrack", "Cell_Across_Swath_5km"); 289 table.put("Track", "Cell_Along_Swath_5km"); 290 table.put("geo_Track", "Cell_Along_Swath_5km"); 291 table.put("geo_XTrack", "Cell_Across_Swath_5km"); 292 table.put("scale_name", "scale_factor"); 293 table.put("offset_name", "add_offset"); 294 table.put("fill_value_name", "_FillValue"); 295 table.put("range_name", arrayNames_5km[k]); 296 297 SwathAdapter swathAdapter = new SwathAdapter(reader, table); 298 defaultSubset = swathAdapter.getDefaultSubset(); 299 adapters[arrayNames.length+k] = swathAdapter; 300 defaultSubsets[arrayNames.length+k] = defaultSubset; 301 categoriesArray[arrayNames.length+k] = DataCategory.parseCategories("5km swath;GRID-2D;"); 302 } 303 } 304 else if (name.contains("HSRL2_B200") && name.endsWith(".h5")) { 305 Map<String, Object> table; 306 307 String dataPath = "DataProducts/"; 308 String[] arrayNames = new String[] {"532_total_attn_bsc", "1064_total_attn_bsc", "355_total_attn_bsc"}; 309 String[] rangeNames = new String[] {"Total_Attenuated_Backscatter_532", "Total_Attenuated_Backscatter_1064", "Total_Attenuated_Backscatter_355"}; 310 311 String[] arrayNameAOT = new String[] {"532_AOT_hi_col", "355_AOT_hi_col"}; 312 String[] rangeNamesAOT = new String[] {}; 313 314 int numAdapters = arrayNames.length; 315 adapters = new MultiDimensionAdapter[numAdapters]; 316 defaultSubsets = new HashMap[numAdapters]; 317 propsArray = new Hashtable[numAdapters]; 318 319 for (int k = 0; k < numAdapters; k++) { 320 table = ProfileAlongTrack.getEmptyMetadataTable(); 321 table.put(ProfileAlongTrack.array_name, dataPath+arrayNames[k]); 322 table.put(ProfileAlongTrack.range_name, rangeNames[k]); 323 table.put(ProfileAlongTrack.trackDim_name, "dim0"); 324 table.put(ProfileAlongTrack.vertDim_name, "dim1"); 325 table.put(ProfileAlongTrack.profileTime_name, "ApplanixIMU/gps_time"); 326 table.put(ProfileAlongTrack.longitude_name, "ApplanixIMU/gps_lon"); 327 table.put(ProfileAlongTrack.latitude_name, "ApplanixIMU/gps_lat"); 328 table.put("array_dimension_names", new String[] {"dim0", "dim1"}); 329 ProfileAlongTrack adapter = new HSRL2D(reader, table); 330 ProfileAlongTrack3D adapter3D = new ProfileAlongTrack3D(adapter); 331 Map<String, double[]> subset = adapter.getDefaultSubset(); 332 adapters[k] = adapter3D; 333 defaultSubset = subset; 334 defaultSubsets[k] = defaultSubset; 335 336 properties.put("medianFilter", new String[] {Integer.toString(adapter.getMedianFilterWindowHeight()), Integer.toString(adapter.getMedianFilterWindowWidth())}); 337 properties.put("setBelowSfcMissing", new String[] {"true"}); 338 propsArray[k] = properties; 339 } 340 341 DataCategory.createCategory("ProfileAlongTrack"); 342 categories = DataCategory.parseCategories("ProfileAlongTrack;ProfileAlongTrack;"); 343 344 hasTrackPreview = true; 345 346 ArrayAdapter[] adapter_s = new ArrayAdapter[3]; 347 table = ProfileAlongTrack.getEmptyMetadataTable(); 348 table.put(ProfileAlongTrack.array_name, "ApplanixIMU/gps_lat"); 349 table.put(ProfileAlongTrack.trackDim_name, "dim0"); 350 table.put(ProfileAlongTrack.vertDim_name, "dim1"); 351 table.put("array_dimension_names", new String[] {"dim0", "dim1"}); 352 adapter_s[0] = new ArrayAdapter(reader, table); 353 354 table = ProfileAlongTrack.getEmptyMetadataTable(); 355 table.put(ProfileAlongTrack.array_name, "UserInput/DEM_altitude"); 356 table.put(ProfileAlongTrack.trackDim_name, "dim0"); 357 table.put(ProfileAlongTrack.vertDim_name, "dim1"); 358 table.put("array_dimension_names", new String[] {"dim0", "dim1"}); 359 adapter_s[1] = new ArrayAdapter(reader, table); 360 /* 361 adapter_s[1].setRangeProcessor(new RangeProcessor() { // Eventually handle unit conversions better. 362 public float[] processRange(float[] fvals, Map<String, double[]> subset) { 363 for (int i=0; i<fvals.length; i++) { 364 fvals[i] *= 1000; //km -> m 365 } 366 return fvals; 367 } 368 }); 369 */ 370 371 table = ProfileAlongTrack.getEmptyMetadataTable(); 372 table.put(ProfileAlongTrack.array_name, "ApplanixIMU/gps_lon"); 373 table.put(ProfileAlongTrack.trackDim_name, "dim0"); 374 table.put(ProfileAlongTrack.vertDim_name, "dim1"); 375 table.put("array_dimension_names", new String[] {"dim0", "dim1"}); 376 adapter_s[2] = new ArrayAdapter(reader, table); 377 378 TrackDomain track_domain = new TrackDomain(adapter_s[2], adapter_s[0], adapter_s[1]); 379 track_adapter = new TrackAdapter(track_domain, adapter_s[1]); 380 381 TrackAdapter trkAdapter = new TrackAdapter(new TrackDomain(adapter_s[2], adapter_s[0], adapter_s[1]), adapter_s[1]); 382 trkAdapter.setName("Track3D"); 383 384 trkAdapter = new TrackAdapter(new TrackDomain(adapter_s[2], adapter_s[0]), adapter_s[1]); 385 trkAdapter.setName("Track2D"); 386 } 387 else if (name.startsWith("CAL_LID_L1")) { 388 389 // Make sure the variables we need are present. If not, this is not a valid 390 // L1 CALIPSO file McV can work with. 391 392 if (! ((hasVariable("Latitude")) && 393 (hasVariable("Longitude")) && 394 (hasVariable("Surface_Elevation")) && 395 (hasVariable("Tropopause_Height")) && 396 (hasVariable("Total_Attenuated_Backscatter_532"))) 397 ) { 398 // Pop up a dialog letting user know we can't work wit this data 399 String msg = "McIDAS-V is unable to read this Level 1 CALIPSO file.\n" + 400 "If you believe this is a valid file which should be supported,\n" + 401 "please contact the MUG or post a message on the MUG Forum."; 402 Object[] params = { msg }; 403 JOptionPane.showMessageDialog(null, params, "Data Validity Test Failure", JOptionPane.OK_OPTION); 404 throw new Exception("Unable to load CALIPSO data"); 405 } 406 407 adapters = new MultiDimensionAdapter[4]; 408 defaultSubsets = new HashMap[4]; 409 propsArray = new Hashtable[4]; 410 411 Map<String, Object> table = ProfileAlongTrack.getEmptyMetadataTable(); 412 table.put(ProfileAlongTrack.array_name, "Total_Attenuated_Backscatter_532"); 413 table.put(ProfileAlongTrack.ancillary_file_name, "/edu/wisc/ssec/mcidasv/data/hydra/resources/calipso/altitude"); 414 table.put(ProfileAlongTrack.trackDim_name, "dim0"); 415 table.put(ProfileAlongTrack.vertDim_name, "dim1"); 416 table.put(ProfileAlongTrack.profileTime_name, "Profile_Time"); 417 table.put(ProfileAlongTrack.longitude_name, "Longitude"); 418 table.put(ProfileAlongTrack.latitude_name, "Latitude"); 419 table.put("array_dimension_names", new String[] {"dim0", "dim1"}); 420 ProfileAlongTrack adapter = new Calipso2D(reader, table); 421 ProfileAlongTrack3D adapter3D = new ProfileAlongTrack3D(adapter); 422 Map<String, double[]> subset = adapter.getDefaultSubset(); 423 adapters[0] = adapter3D; 424 defaultSubset = subset; 425 defaultSubsets[0] = defaultSubset; 426 DataCategory.createCategory("ProfileAlongTrack"); 427 categories = DataCategory.parseCategories("ProfileAlongTrack;ProfileAlongTrack;"); 428 429 properties.put("medianFilter", new String[] {Integer.toString(adapter.getMedianFilterWindowHeight()), Integer.toString(adapter.getMedianFilterWindowWidth())}); 430 properties.put("setBelowSfcMissing", new String[] {"true"}); 431 propsArray[0] = properties; 432 433 ArrayAdapter[] adapter_s = new ArrayAdapter[3]; 434 table = ProfileAlongTrack.getEmptyMetadataTable(); 435 table.put(ProfileAlongTrack.array_name, "Latitude"); 436 table.put(ProfileAlongTrack.trackDim_name, "dim0"); 437 table.put(ProfileAlongTrack.vertDim_name, "dim1"); 438 table.put("array_dimension_names", new String[] {"dim0", "dim1"}); 439 adapter_s[0] = new ArrayAdapter(reader, table); 440 441 table = ProfileAlongTrack.getEmptyMetadataTable(); 442 table.put(ProfileAlongTrack.array_name, "Surface_Elevation"); 443 table.put(ProfileAlongTrack.trackDim_name, "dim0"); 444 table.put(ProfileAlongTrack.vertDim_name, "dim1"); 445 table.put("array_dimension_names", new String[] {"dim0", "dim1"}); 446 adapter_s[1] = new ArrayAdapter(reader, table); 447 adapter_s[1].setRangeProcessor(new RangeProcessor() { // Eventually handle unit conversions better. 448 public float[] processRange(float[] fvals, Map<String, double[]> subset) { 449 for (int i=0; i<fvals.length; i++) { 450 fvals[i] *= 1000; //km -> m 451 } 452 return fvals; 453 } 454 }); 455 456 table = ProfileAlongTrack.getEmptyMetadataTable(); 457 table.put(ProfileAlongTrack.array_name, "Longitude"); 458 table.put(ProfileAlongTrack.trackDim_name, "dim0"); 459 table.put(ProfileAlongTrack.vertDim_name, "dim1"); 460 table.put("array_dimension_names", new String[] {"dim0", "dim1"}); 461 adapter_s[2] = new ArrayAdapter(reader, table); 462 463 TrackDomain track_domain = new TrackDomain(adapter_s[2], adapter_s[0], adapter_s[1]); 464 track_adapter = new TrackAdapter(track_domain, adapter_s[1]); 465 466 table = ProfileAlongTrack.getEmptyMetadataTable(); 467 table.put(ProfileAlongTrack.array_name, "Tropopause_Height"); 468 table.put(ProfileAlongTrack.trackDim_name, "dim0"); 469 table.put(ProfileAlongTrack.vertDim_name, "dim1"); 470 table.put("array_dimension_names", new String[] {"dim0", "dim1"}); 471 ArrayAdapter trop_height = new ArrayAdapter(reader, table); 472 track_domain = new TrackDomain(adapter_s[2], adapter_s[0], trop_height); 473 adapters[1] = new TrackAdapter(track_domain, trop_height); 474 defaultSubsets[1] = adapters[1].getDefaultSubset(); 475 476 adapters[2] = new TrackAdapter(new TrackDomain(adapter_s[2], adapter_s[0], adapter_s[1]), adapter_s[1]); 477 ((TrackAdapter)adapters[2]).setName("Track3D"); 478 defaultSubsets[2] = adapters[2].getDefaultSubset(); 479 480 adapters[3] = new TrackAdapter(new TrackDomain(adapter_s[2], adapter_s[0]), adapter_s[1]); 481 ((TrackAdapter)adapters[3]).setName("Track2D"); 482 defaultSubsets[3] = adapters[3].getDefaultSubset(); 483 484 485 hasTrackPreview = true; 486 } 487 else if (name.startsWith("CAL_LID_L2")) { 488 489 // Make sure the variables we need are present. If not, this is not a valid 490 // L2 CALIPSO file McV can work with. 491 492 if (! ((hasVariable("Latitude")) && 493 (hasVariable("Longitude")) && 494 (hasVariable("DEM_Surface_Elevation")) && 495 (hasVariable("Layer_Top_Altitude"))) 496 ) { 497 // Pop up a dialog letting user know we can't work wit this data 498 String msg = "McIDAS-V is unable to read this Level 2 CALIPSO file.\n" + 499 "If you believe this is a valid file which should be supported,\n" + 500 "please contact the MUG or post a message on the MUG Forum."; 501 Object[] params = { msg }; 502 JOptionPane.showMessageDialog(null, params, "Data Validity Test Failure", JOptionPane.OK_OPTION); 503 throw new Exception("Unable to load CALIPSO data"); 504 } 505 506 adapters = new MultiDimensionAdapter[4]; 507 defaultSubsets = new HashMap[4]; 508 propsArray = new Hashtable[4]; 509 510 ArrayAdapter[] adapter_s = new ArrayAdapter[3]; 511 512 adapter_s[0] = createTrackVertArrayAdapter("Longitude"); 513 adapter_s[1] = createTrackVertArrayAdapter("Latitude"); 514 adapter_s[2] = createTrackVertArrayAdapter("DEM_Surface_Elevation"); 515 516 TrackDomain track_domain = new TrackDomain(adapter_s[0], adapter_s[1], adapter_s[2]); 517 track_adapter = new TrackAdapter(track_domain, adapter_s[2]); 518 adapters[1] = track_adapter; 519 defaultSubsets[1] = track_adapter.getDefaultSubset(); 520 521 ArrayAdapter layer_top_altitude = createTrackVertArrayAdapter("Layer_Top_Altitude"); 522 523 RangeProcessor rngProcessor = 524 new RangeProcessor(1.0f, 0.0f, -Float.MAX_VALUE, Float.MAX_VALUE, -9999.0f); 525 layer_top_altitude.setRangeProcessor(rngProcessor); 526 527 track_domain = new TrackDomain(adapter_s[0], adapter_s[1], layer_top_altitude); 528 adapters[0] = new TrackAdapter(track_domain, layer_top_altitude); 529 defaultSubsets[0] = adapters[0].getDefaultSubset(); 530 531 /** another layer, how to show all? 532 adapters[2] = new TrackAdapter(track_domain, layer_top_altitude); 533 ((TrackAdapter)adapters[2]).setListIndex(1); 534 defaultSubsets[2] = adapters[2].getDefaultSubset(); 535 */ 536 537 adapters[2] = new TrackAdapter(new TrackDomain(adapter_s[0], adapter_s[1]), adapter_s[2]); 538 ((TrackAdapter)adapters[2]).setName("Track2D"); 539 defaultSubsets[2] = adapters[2].getDefaultSubset(); 540 541 adapters[3] = new TrackAdapter(new TrackDomain(adapter_s[0], adapter_s[1], adapter_s[2]), adapter_s[2]); 542 ((TrackAdapter)adapters[3]).setName("Track3D"); 543 defaultSubsets[3] = adapters[3].getDefaultSubset(); 544 545 DataCategory.createCategory("ProfileAlongTrack"); 546 categories = DataCategory.parseCategories("ProfileAlongTrack;ProfileAlongTrack;"); 547 548 hasTrackPreview = true; 549 } 550 else if (name.indexOf("2B-GEOPROF") > 0) { 551 adapters = new MultiDimensionAdapter[3]; 552 defaultSubsets = new HashMap[3]; 553 propsArray = new Hashtable[3]; 554 555 Map<String, Object> table = ProfileAlongTrack.getEmptyMetadataTable(); 556 table.put(ProfileAlongTrack.array_name, "2B-GEOPROF/Data_Fields/Radar_Reflectivity"); 557 table.put(ProfileAlongTrack.range_name, "2B-GEOPROF_RadarReflectivity"); 558 table.put(ProfileAlongTrack.scale_name, "factor"); 559 table.put(ProfileAlongTrack.offset_name, "offset"); 560 table.put(ProfileAlongTrack.fill_value_name, "_FillValue"); 561 table.put(ProfileAlongTrack.valid_range, "valid_range"); 562 table.put(ProfileAlongTrack.ancillary_file_name, "/edu/wisc/ssec/mcidasv/data/hydra/resources/cloudsat/altitude"); 563 table.put(ProfileAlongTrack.trackDim_name, "nray"); 564 table.put(ProfileAlongTrack.vertDim_name, "nbin"); 565 table.put(ProfileAlongTrack.profileTime_name, "2B-GEOPROF/Geolocation_Fields/Profile_Time"); 566 table.put(ProfileAlongTrack.longitude_name, "2B-GEOPROF/Geolocation_Fields/Longitude"); 567 table.put(ProfileAlongTrack.latitude_name, "2B-GEOPROF/Geolocation_Fields/Latitude"); 568 table.put(ProfileAlongTrack.product_name, "2B-GEOPROF"); 569 ProfileAlongTrack adapter = new CloudSat2D(reader, table); 570 ProfileAlongTrack3D adapter3D = new ProfileAlongTrack3D(adapter); 571 Map<String, double[]> subset = adapter.getDefaultSubset(); 572 adapters[0] = adapter3D; 573 defaultSubset = subset; 574 defaultSubsets[0] = defaultSubset; 575 DataCategory.createCategory("ProfileAlongTrack"); 576 categories = DataCategory.parseCategories("ProfileAlongTrack;ProfileAlongTrack;"); 577 578 ArrayAdapter[] adapter_s = new ArrayAdapter[3]; 579 table = ProfileAlongTrack.getEmptyMetadataTable(); 580 table.put(ProfileAlongTrack.array_name, "2B-GEOPROF/Geolocation_Fields/Latitude"); 581 table.put(ProfileAlongTrack.range_name, "Latitude"); 582 table.put(ProfileAlongTrack.trackDim_name, "nray"); 583 adapter_s[0] = new ArrayAdapter(reader, table); 584 585 table = ProfileAlongTrack.getEmptyMetadataTable(); 586 table.put(ProfileAlongTrack.array_name, "2B-GEOPROF/Geolocation_Fields/DEM_elevation"); 587 table.put(ProfileAlongTrack.range_name, "DEM_elevation"); 588 table.put(ProfileAlongTrack.trackDim_name, "nray"); 589 adapter_s[1] = new ArrayAdapter(reader, table); 590 adapter_s[1].setRangeProcessor(new RangeProcessor() { // need this because we don't want -9999 mapped to NaN 591 public float[] processRange(short[] svals, Map<String, double[]> subset) { 592 float[] fvals = new float[svals.length]; 593 for (int i=0; i<svals.length; i++) { 594 short sval = svals[i]; 595 if (sval == -9999) { 596 fvals[i] = 0f; 597 } 598 else { 599 fvals[i] = sval; 600 } 601 } 602 return fvals; 603 } 604 }); 605 606 table = ProfileAlongTrack.getEmptyMetadataTable(); 607 table.put(ProfileAlongTrack.array_name, "2B-GEOPROF/Geolocation_Fields/Longitude"); 608 table.put(ProfileAlongTrack.range_name, "Longitude"); 609 table.put(ProfileAlongTrack.trackDim_name, "nray"); 610 adapter_s[2] = new ArrayAdapter(reader, table); 611 612 TrackDomain track_domain = new TrackDomain(adapter_s[2], adapter_s[0], adapter_s[1]); 613 track_adapter = new TrackAdapter(track_domain, adapter_s[1]); 614 615 adapters[2] = new TrackAdapter(new TrackDomain(adapter_s[2], adapter_s[0], adapter_s[1]), adapter_s[1]); 616 ((TrackAdapter)adapters[2]).setName("Track3D"); 617 defaultSubsets[2] = adapters[2].getDefaultSubset(); 618 619 adapters[1] = new TrackAdapter(new TrackDomain(adapter_s[2], adapter_s[0]), adapter_s[1]); 620 ((TrackAdapter)adapters[1]).setName("Track2D"); 621 defaultSubsets[1] = adapters[1].getDefaultSubset(); 622 623 624 properties.put("medianFilter", new String[] {Integer.toString(adapter.getMedianFilterWindowHeight()), Integer.toString(adapter.getMedianFilterWindowWidth())}); 625 properties.put("setBelowSfcMissing", new String[] {"true"}); 626 propsArray[0] = properties; 627 hasTrackPreview = true; 628 } 629 else if ( name.startsWith("MHSx_xxx_1B") && name.endsWith("h5")) { 630 Map<String, Object> table = SwathAdapter.getEmptyMetadataTable(); 631 table.put("array_name", "U-MARF/EPS/MHSx_xxx_1B/DATA/Channel1"); 632 table.put("lon_array_name", "U-MARF/EPS/IASI_xxx_1C/DATA/IMAGE_LON_ARRAY"); 633 table.put("lat_array_name", "U-MARF/EPS/IASI_xxx_1C/DATA/IMAGE_LAT_ARRAY"); 634 table.put("XTrack", "dim1"); 635 table.put("Track", "dim0"); 636 table.put("geo_XTrack", "dim1"); 637 table.put("geo_Track", "dim0"); 638 table.put("product_name", "MHSx_xxx_1B"); 639 SwathAdapter swathAdapter = new SwathAdapter(reader, table); 640 adapters[0] = swathAdapter; 641 Map<String, double[]> subset = swathAdapter.getDefaultSubset(); 642 defaultSubset = subset; 643 defaultSubsets[0] = defaultSubset; 644 categories = DataCategory.parseCategories("2D grid;GRID-2D;"); 645 } 646 else if ( name.startsWith("MYD02SSH") ) { 647 String[] arrayNames = null; 648 649 if (name.endsWith("level2.hdf")) { 650 arrayNames = new String[] {"cld_press_acha", "cld_temp_acha", "cld_height_acha", "cloud_type", 651 "cloud_albedo_0_65um_nom", "cloud_transmission_0_65um_nom", "cloud_fraction"}; 652 } 653 else if (name.endsWith("obs.hdf")) { 654 arrayNames = new String[] {"refl_0_65um_nom", "refl_0_86um_nom", "refl_3_75um_nom", "refl_1_60um_nom", "refl_1_38um_nom", 655 "temp_3_75um_nom", "temp_11_0um_nom", "temp_12_0um_nom", "temp_6_7um_nom", 656 "temp_8_5um_nom", "temp_13_3um_nom"}; 657 } 658 659 adapters = new MultiDimensionAdapter[arrayNames.length]; 660 defaultSubsets = new HashMap[arrayNames.length]; 661 propsArray = new Hashtable[arrayNames.length]; 662 663 for (int k=0; k<arrayNames.length; k++) { 664 Map<String, Object> swthTable = SwathAdapter.getEmptyMetadataTable(); 665 swthTable.put("array_name", arrayNames[k]); 666 swthTable.put("lon_array_name", "pixel_longitude"); 667 swthTable.put("lat_array_name", "pixel_latitude"); 668 swthTable.put("XTrack", "pixel_elements_along_scan_direction"); 669 swthTable.put("Track", "scan_lines_along_track_direction"); 670 swthTable.put("geo_Track", "scan_lines_along_track_direction"); 671 swthTable.put("geo_XTrack", "pixel_elements_along_scan_direction"); 672 swthTable.put("scale_name", "SCALE_FACTOR"); 673 swthTable.put("offset_name", "ADD_OFFSET"); 674 swthTable.put("fill_value_name", "_FILLVALUE"); 675 swthTable.put("geo_scale_name", "SCALE_FACTOR"); 676 swthTable.put("geo_offset_name", "ADD_OFFSET"); 677 swthTable.put("geo_fillValue_name", "_FILLVALUE"); 678 swthTable.put("range_name", arrayNames[k]); 679 swthTable.put("unpack", "unpack"); 680 681 SwathAdapter swathAdapter0 = new SwathAdapter(reader, swthTable); 682 Map<String, double[]> subset = swathAdapter0.getDefaultSubset(); 683 defaultSubset = subset; 684 adapters[k] = swathAdapter0; 685 defaultSubsets[k] = defaultSubset; 686 } 687 categories = DataCategory.parseCategories("2D grid;GRID-2D;"); 688 hasImagePreview = true; 689 } 690 else if (name.contains("AWG_OZONE") ) { 691 String[] arrayNames = new String[] {"ColumnOzone"}; 692 693 adapters = new MultiDimensionAdapter[arrayNames.length]; 694 defaultSubsets = new HashMap[arrayNames.length]; 695 propsArray = new Hashtable[arrayNames.length]; 696 697 for (int k=0; k<arrayNames.length; k++) { 698 Map<String, Object> swthTable = SwathAdapter.getEmptyMetadataTable(); 699 swthTable.put("array_name", arrayNames[k]); 700 swthTable.put("lon_array_name", "Longitude"); 701 swthTable.put("lat_array_name", "Latitude"); 702 swthTable.put("XTrack", "Columns"); 703 swthTable.put("Track", "Rows"); 704 swthTable.put("fill_value_name", "_FillValue"); 705 swthTable.put("geo_Track", "Rows"); 706 swthTable.put("geo_XTrack", "Columns"); 707 swthTable.put("geo_fillValue_name", "_FillValue"); 708 swthTable.put("range_name", arrayNames[k]); 709 710 SwathAdapter swathAdapter0 = new SwathAdapter(reader, swthTable); 711 swathAdapter0.setDefaultStride(5); 712 Map<String, double[]> subset = swathAdapter0.getDefaultSubset(); 713 defaultSubset = subset; 714 adapters[k] = swathAdapter0; 715 defaultSubsets[k] = defaultSubset; 716 } 717 718 categories = DataCategory.parseCategories("2D grid;GRID-2D;"); 719 hasImagePreview = true; 720 } 721 else if (name.contains("AWG_CLOUD_MASK") ) { 722 String[] arrayNames = new String[] {"CloudMask"}; 723 724 adapters = new MultiDimensionAdapter[arrayNames.length]; 725 defaultSubsets = new HashMap[arrayNames.length]; 726 propsArray = new Hashtable[arrayNames.length]; 727 728 for (int k=0; k<arrayNames.length; k++) { 729 Map<String, Object> swthTable = SwathAdapter.getEmptyMetadataTable(); 730 swthTable.put("array_name", arrayNames[k]); 731 swthTable.put("lon_array_name", "Longitude"); 732 swthTable.put("lat_array_name", "Latitude"); 733 swthTable.put("XTrack", "Columns"); 734 swthTable.put("Track", "Rows"); 735 swthTable.put("fill_value_name", "_FillValue"); 736 swthTable.put("geo_Track", "Rows"); 737 swthTable.put("geo_XTrack", "Columns"); 738 swthTable.put("geo_fillValue_name", "_FillValue"); 739 swthTable.put("range_name", arrayNames[k]); 740 741 SwathAdapter swathAdapter0 = new SwathAdapter(reader, swthTable); 742 swathAdapter0.setDefaultStride(5); 743 Map<String, double[]> subset = swathAdapter0.getDefaultSubset(); 744 defaultSubset = subset; 745 adapters[k] = swathAdapter0; 746 defaultSubsets[k] = defaultSubset; 747 } 748 749 categories = DataCategory.parseCategories("2D grid;GRID-2D;"); 750 hasImagePreview = true; 751 } 752 else if (name.contains("AWG_CLOUD_HEIGHT")) { 753 String[] arrayNames = new String[] {"CldTopTemp", "CldTopPres", "CldTopHght"}; 754 755 adapters = new MultiDimensionAdapter[arrayNames.length]; 756 defaultSubsets = new HashMap[arrayNames.length]; 757 propsArray = new Hashtable[arrayNames.length]; 758 759 for (int k=0; k<arrayNames.length; k++) { 760 Map<String, Object> swthTable = SwathAdapter.getEmptyMetadataTable(); 761 swthTable.put("array_name", arrayNames[k]); 762 swthTable.put("lon_array_name", "Longitude"); 763 swthTable.put("lat_array_name", "Latitude"); 764 swthTable.put("XTrack", "Columns"); 765 swthTable.put("Track", "Rows"); 766 swthTable.put("scale_name", "scale_factor"); 767 swthTable.put("offset_name", "add_offset"); 768 swthTable.put("fill_value_name", "_FillValue"); 769 swthTable.put("geo_Track", "Rows"); 770 swthTable.put("geo_XTrack", "Columns"); 771 swthTable.put("geo_scale_name", "scale_factor"); 772 swthTable.put("geo_offset_name", "add_offset"); 773 swthTable.put("geo_fillValue_name", "_FillValue"); 774 swthTable.put("range_name", arrayNames[k]); 775 swthTable.put("unpack", "unpack"); 776 777 SwathAdapter swathAdapter0 = new SwathAdapter(reader, swthTable); 778 swathAdapter0.setDefaultStride(5); 779 Map<String, double[]> subset = swathAdapter0.getDefaultSubset(); 780 defaultSubset = subset; 781 adapters[k] = swathAdapter0; 782 defaultSubsets[k] = defaultSubset; 783 } 784 categories = DataCategory.parseCategories("2D grid;GRID-2D;"); 785 hasImagePreview = true; 786 } 787 else if (name.startsWith("geocatL2") && name.endsWith("ci.hdf")) { 788 String[] arrayNames = new String[] {"box_average_11um_ctc", "box_average_11um_ctc_scaled", "conv_init", "cloud_type"}; 789 790 adapters = new MultiDimensionAdapter[arrayNames.length]; 791 defaultSubsets = new HashMap[arrayNames.length]; 792 propsArray = new Hashtable[arrayNames.length]; 793 794 for (int k=0; k<arrayNames.length; k++) { 795 Map<String, Object> swthTable = SwathAdapter.getEmptyMetadataTable(); 796 swthTable.put("array_name", arrayNames[k]); 797 swthTable.put("lon_array_name", "lon"); 798 swthTable.put("lat_array_name", "lat"); 799 swthTable.put("XTrack", "Elements"); 800 swthTable.put("Track", "Lines"); 801 swthTable.put("geo_Track", "Lines"); 802 swthTable.put("geo_XTrack", "Elements"); 803 swthTable.put("range_name", arrayNames[k]); 804 805 SwathAdapter swathAdapter0 = new SwathAdapter(reader, swthTable); 806 swathAdapter0.setDefaultStride(1); 807 Map<String, double[]> subset = swathAdapter0.getDefaultSubset(); 808 defaultSubset = subset; 809 adapters[k] = swathAdapter0; 810 defaultSubsets[k] = defaultSubset; 811 } 812 categories = DataCategory.parseCategories("2D grid;GRID-2D;"); 813 hasImagePreview = true; 814 } 815 else { 816 String[] arrayNames = new String[] {"baseline_cmask_seviri_cloud_mask", "baseline_ctype_seviri_cloud_type", 817 "baseline_ctype_seviri_cloud_phase", "baseline_cld_hght_seviri_cloud_top_pressure", 818 "baseline_cld_hght_seviri_cloud_top_height"}; 819 820 adapters = new MultiDimensionAdapter[arrayNames.length]; 821 defaultSubsets = new HashMap[arrayNames.length]; 822 propsArray = new Hashtable[arrayNames.length]; 823 824 for (int k=0; k<arrayNames.length; k++) { 825 Map<String, Object> swthTable = SwathAdapter.getEmptyMetadataTable(); 826 swthTable.put("array_name", arrayNames[k]); 827 swthTable.put("lon_array_name", "pixel_longitude"); 828 swthTable.put("lat_array_name", "pixel_latitude"); 829 swthTable.put("XTrack", "elements"); 830 swthTable.put("Track", "lines"); 831 swthTable.put("scale_name", "scale_factor"); 832 swthTable.put("offset_name", "add_offset"); 833 swthTable.put("fill_value_name", "_FillValue"); 834 swthTable.put("geo_Track", "lines"); 835 swthTable.put("geo_XTrack", "elements"); 836 swthTable.put("geo_scale_name", "scale_factor"); 837 swthTable.put("geo_offset_name", "add_offset"); 838 swthTable.put("geo_fillValue_name", "_FillValue"); 839 swthTable.put("range_name", arrayNames[k]); 840 swthTable.put("unpack", "unpack"); 841 842 SwathAdapter swathAdapter0 = new SwathAdapter(reader, swthTable); 843 swathAdapter0.setDefaultStride(2); 844 Map<String, double[]> subset = swathAdapter0.getDefaultSubset(); 845 defaultSubset = subset; 846 adapters[k] = swathAdapter0; 847 defaultSubsets[k] = defaultSubset; 848 } 849 categories = DataCategory.parseCategories("2D grid;GRID-2D;"); 850 hasImagePreview = true; 851 } 852 853 setProperties(properties); 854 } 855 856 public void initAfterUnpersistence() { 857 try { 858 setup(); 859 } catch (Exception e) { 860 logger.error("could not set up after unpersisting", e); 861 } 862 } 863 864 /** 865 * Make and insert the {@link DataChoice DataChoices} for this {@code DataSource}. 866 */ 867 public void doMakeDataChoices() { 868 DataChoice choice = null; 869 if (adapters != null) { 870 for (int idx=0; idx<adapters.length; idx++) { 871 try { 872 String arrayName = (adapters[idx] == null) ? "_ " : adapters[idx].getArrayName(); 873 choice = doMakeDataChoice(idx, arrayName); 874 adapterMap.put(choice.getName(), adapters[idx]); 875 } catch (Exception e) { 876 logger.error("error making data choices", e); 877 } 878 879 if (choice != null) { 880 addDataChoice(choice); 881 } 882 } 883 } 884 } 885 886 private DataChoice doMakeDataChoice(int idx, String var) throws Exception { 887 String name = var; 888 DataSelection dataSel = (defaultSubsets[idx] == null) ? new MultiDimensionSubset() : new MultiDimensionSubset(defaultSubsets[idx]); 889 Hashtable props = new Hashtable(); 890 props.put(new MultiDimensionSubset(), dataSel); 891 892 if (propsArray != null) { 893 if (propsArray[idx] != null) { 894 propsArray[idx].put(new MultiDimensionSubset(), dataSel); 895 props = propsArray[idx]; 896 } 897 } 898 DirectDataChoice ddc = null; 899 900 if (categories != null) { 901 ddc = new DirectDataChoice(this, idx, name, name, categories, props); 902 } 903 else { 904 ddc = new DirectDataChoice(this, idx, name, name, categoriesArray[idx], props); 905 } 906 907 return ddc; 908 } 909 910 /** 911 * Check to see if this {@code HDFHydraDataSource} is equal to the object 912 * in question. 913 * @param o object in question 914 * @return true if they are the same or equivalent objects 915 */ 916 public boolean equals(Object o) { 917 if ( !(o instanceof MultiDimensionDataSource)) { 918 return false; 919 } 920 return (this == (MultiDimensionDataSource) o); 921 } 922 923 public MultiSpectralData getMultiSpectralData() { 924 return multiSpectData; 925 } 926 927 public String getDatasetName() { 928 return filename; 929 } 930 931 public void setDatasetName(String name) { 932 filename = name; 933 } 934 935 public Map<String, double[]> getSubsetFromLonLatRect(MultiDimensionSubset select, GeoSelection geoSelection) { 936 GeoLocationInfo ginfo = geoSelection.getBoundingBox(); 937 logger.debug("ginfo0: " + ginfo); 938 return adapters[0].getSubsetFromLonLatRect(select.getSubset(), ginfo.getMinLat(), ginfo.getMaxLat(), 939 ginfo.getMinLon(), ginfo.getMaxLon()); 940 } 941 942 public synchronized Data getData(DataChoice dataChoice, DataCategory category, 943 DataSelection dataSelection, Hashtable requestProperties) 944 throws VisADException, RemoteException { 945 return this.getDataInner(dataChoice, category, dataSelection, requestProperties); 946 } 947 948 949 protected Data getDataInner(DataChoice dataChoice, DataCategory category, 950 DataSelection dataSelection, Hashtable requestProperties) 951 throws VisADException, RemoteException { 952 953 MultiDimensionAdapter adapter = null; 954 adapter = adapterMap.get(dataChoice.getName()); 955 956 Hashtable dataChoiceProps = dataChoice.getProperties(); 957 958 //- this hack keeps the HydraImageProbe from doing a getData() 959 //- TODO: need to use categories? 960 if (requestProperties != null) { 961 if ((requestProperties.toString()).equals("{prop.requester=MultiSpectral}")) { 962 return null; 963 } 964 } 965 966 GeoLocationInfo ginfo = null; 967 GeoSelection geoSelection = null; 968 969 if ((dataSelection != null) && (dataSelection.getGeoSelection() != null)) { 970 971 if (dataSelection.getGeoSelection().getBoundingBox() != null) { 972 geoSelection = dataSelection.getGeoSelection(); 973 } 974 else { // no bounding box in the incoming DataSelection. Check the dataChoice. 975 DataSelection datSelFromChoice = dataChoice.getDataSelection(); 976 if (datSelFromChoice != null) { 977 geoSelection = datSelFromChoice.getGeoSelection(); 978 } 979 } 980 } 981 982 if (geoSelection != null) { 983 ginfo = geoSelection.getBoundingBox(); 984 } 985 986 // Still no geo info so check for the lon/lat b.b. in this datasource (last set by DataSelectionComponent) 987 if (ginfo == null) { 988 DataSelection localDataSelection = getDataSelection(); 989 if (localDataSelection != null) { 990 geoSelection = localDataSelection.getGeoSelection(); 991 if (geoSelection != null) { 992 ginfo = geoSelection.getBoundingBox(); 993 } 994 } 995 } 996 997 Data data = null; 998 if (adapters == null) { 999 return data; 1000 } 1001 1002 Map<String, double[]> subset = null; 1003 MultiDimensionSubset select = null; 1004 1005 Hashtable table = dataChoice.getProperties(); 1006 Enumeration keys = table.keys(); 1007 while (keys.hasMoreElements()) { 1008 Object key = keys.nextElement(); 1009 if (key instanceof MultiDimensionSubset) { 1010 select = (MultiDimensionSubset) table.get(key); 1011 } 1012 } 1013 1014 try { 1015 subset = null; 1016 if (ginfo != null) { 1017 if (trackSelection != null) { 1018 boolean trackStrideOk = trackSelection.setTrackStride(); 1019 boolean verticalStrideOk = trackSelection.setVerticalStride(); 1020 1021 if (trackStrideOk && verticalStrideOk) { 1022 subset = adapter.getSubsetFromLonLatRect(ginfo.getMinLat(), ginfo.getMaxLat(), 1023 ginfo.getMinLon(), ginfo.getMaxLon(), 1024 trackSelection.trackStride, 1025 trackSelection.verticalStride, 1026 geoSelection.getZStride()); 1027 } else { 1028 // one of the strides is not an integer, let user know 1029 String msg = "Either the Track or Vertical Stride is invalid.\n" + 1030 "Stride values must be positive integers.\n"; 1031 Object[] params = { msg }; 1032 JOptionPane.showMessageDialog(null, params, "Invalid Stride", JOptionPane.OK_OPTION); 1033 return null; 1034 } 1035 } else { 1036 subset = adapter.getSubsetFromLonLatRect(ginfo.getMinLat(), ginfo.getMaxLat(), 1037 ginfo.getMinLon(), ginfo.getMaxLon(), 1038 geoSelection.getXStride(), 1039 geoSelection.getYStride(), 1040 geoSelection.getZStride()); 1041 } 1042 if (subset == null && select != null) { 1043 subset = select.getSubset(); 1044 } 1045 } 1046 else { // no IDV incoming spatial selection info, so check for HYDRA specific via Properties 1047 1048 if (trackSelection != null) { 1049 boolean trackStrideOk = trackSelection.setTrackStride(); 1050 boolean verticalStrideOk = trackSelection.setVerticalStride(); 1051 if ((! trackStrideOk) || (! verticalStrideOk)) { 1052 // one of the strides is not an integer, let user know 1053 String msg = "Either the Track or Vertical Stride is invalid.\n" + 1054 "Stride values must be positive integers.\n"; 1055 Object[] params = { msg }; 1056 JOptionPane.showMessageDialog(null, params, "Invalid Stride", JOptionPane.OK_OPTION); 1057 return null; 1058 } 1059 boolean lengthPercent = trackSelection.setLengthPercent(); 1060 if (! lengthPercent) { 1061 // specified percentage of total track is invalid 1062 String msg = "Percent of total track is invalid.\n" + 1063 "Value must be between 1 and 100.\n"; 1064 Object[] params = { msg }; 1065 JOptionPane.showMessageDialog(null, params, "Invalid Track Percentage", JOptionPane.OK_OPTION); 1066 return null; 1067 } 1068 } 1069 1070 if (select != null) { 1071 subset = select.getSubset(); 1072 } 1073 1074 if (dataSelection != null) { 1075 Hashtable props = dataSelection.getProperties(); 1076 } 1077 } 1078 1079 if (subset != null) { 1080 data = adapter.getData(subset); 1081 data = applyProperties(data, dataChoiceProps, subset); 1082 } 1083 } catch (Exception e) { 1084 logger.error("getData exception", e); 1085 } 1086 1087 return data; 1088 } 1089 1090 protected Data applyProperties(Data data, Hashtable requestProperties, Map<String, double[]> subset) 1091 throws VisADException, RemoteException, Exception { 1092 Data new_data = data; 1093 1094 if (requestProperties == null) { 1095 new_data = data; 1096 return new_data; 1097 } 1098 1099 if (requestProperties.containsKey("medianFilter")) { 1100 String[] items = (String[]) requestProperties.get("medianFilter"); 1101 int windowVertLen = Integer.parseInt(items[0]); 1102 int windowHorzLen = Integer.parseInt(items[1]); 1103 GriddedSet domainSet = (GriddedSet) ((FlatField)data).getDomainSet(); 1104 int[] lens = domainSet.getLengths(); 1105 float[] range_values = (((FlatField)data).getFloats())[0]; 1106 range_values = 1107 ProfileAlongTrack.medianFilter(range_values, lens[0], lens[1], windowHorzLen, windowVertLen); 1108 ((FlatField)new_data).setSamples(new float[][] {range_values}); 1109 } 1110 if (requestProperties.containsKey("setBelowSfcMissing")) { 1111 FlatField track = (FlatField) track_adapter.getData(subset); 1112 float[] sfcElev = (track.getFloats())[0]; 1113 FlatField field = (FlatField) new_data; 1114 GriddedSet gset = (GriddedSet) field.getDomainSet(); 1115 float[][] samples = gset.getSamples(false); 1116 int[] lens = gset.getLengths(); 1117 float[] range_values = (field.getFloats())[0]; 1118 1119 int trkIdx = ((ProfileAlongTrack3D)adapters[0]).adapter2D.getTrackTupIdx(); 1120 int vrtIdx = ((ProfileAlongTrack3D)adapters[0]).adapter2D.getVertTupIdx(); 1121 1122 int k = 0; 1123 for (int j=0; j<lens[trkIdx]; j++) { 1124 float val = sfcElev[j]; 1125 for (int i=0; i<lens[vrtIdx]; i++) { 1126 if (vrtIdx < trkIdx) k = i + j*lens[0]; 1127 if (trkIdx < vrtIdx) k = j + i*lens[0]; 1128 if (samples[2][k] <= val) { 1129 range_values[k] = Float.NaN; 1130 } 1131 } 1132 } 1133 field.setSamples(new float[][] {range_values}); 1134 } 1135 return new_data; 1136 } 1137 1138 protected void initDataSelectionComponents( 1139 List<DataSelectionComponent> components, 1140 final DataChoice dataChoice) { 1141 1142 if (hasImagePreview) { 1143 try { 1144 FlatField image = (FlatField) getDataInner(dataChoice, null, null, null); 1145 components.add(new PreviewSelection(dataChoice, image, null)); 1146 } catch (Exception e) { 1147 logger.error("cannot make preview selection", e); 1148 } 1149 } 1150 if (hasTrackPreview) { 1151 try { 1152 FlatField track = track_adapter.getData(track_adapter.getDefaultSubset()); 1153 Map defaultSubset = (adapterMap.get(dataChoice.getName())).getDefaultSubset(); 1154 trackSelection = new TrackSelection(dataChoice, track, defaultSubset); 1155 components.add(trackSelection); 1156 } catch (Exception e) { 1157 logger.error("cannot make preview selection", e); 1158 } 1159 } 1160 } 1161 1162 private String getTrackDimensionName(String variableName) { 1163 return getVariableDimensionName(variableName, 0); 1164 } 1165 1166 private String getVerticalDimensionName(String variableName) { 1167 return getVariableDimensionName(variableName, 1); 1168 } 1169 1170 private String getVariableDimensionName(String variableName, int dimension) { 1171 NetcdfFile ncfile = ((NetCDFFile)reader).getNetCDFFile(); 1172 Variable v = ncfile.findVariable(variableName); 1173 String name = null; 1174 if (v != null) { 1175 name = v.getDimension(dimension).getFullName(); 1176 } 1177 return name; 1178 } 1179 1180 private boolean hasVariable(String variableName) { 1181 NetcdfFile ncfile = ((NetCDFFile) reader).getNetCDFFile(); 1182 return ncfile.findVariable(variableName) != null; 1183 } 1184 1185 private ArrayAdapter createTrackVertArrayAdapter(String variableName) { 1186 Map<String, Object> table = SwathAdapter.getEmptyMetadataTable(); 1187 1188 String trackDimName = getTrackDimensionName(variableName); 1189 String vertDimName = getVerticalDimensionName(variableName); 1190 1191 table.put(ProfileAlongTrack.array_name, variableName); 1192 table.put(ProfileAlongTrack.trackDim_name, trackDimName); 1193 table.put(ProfileAlongTrack.vertDim_name, vertDimName); 1194 table.put("array_dimension_names", new String[] { trackDimName, vertDimName }); 1195 1196 return new ArrayAdapter(reader, table); 1197 } 1198}