001 /* 002 * This file is part of McIDAS-V 003 * 004 * Copyright 2007-2013 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 http://www.gnu.org/licenses. 027 */ 028 029 package edu.wisc.ssec.mcidasv.data.hrit; 030 031 import java.awt.BorderLayout; 032 import java.awt.FlowLayout; 033 import java.io.File; 034 import java.io.IOException; 035 import java.rmi.RemoteException; 036 import java.util.ArrayList; 037 import java.util.Hashtable; 038 import java.util.List; 039 040 import javax.swing.JComboBox; 041 import javax.swing.JComponent; 042 import javax.swing.JPanel; 043 044 import edu.wisc.ssec.mcidas.Calibrator; 045 046 import visad.Data; 047 import visad.VisADException; 048 import visad.data.hrit.HRITAdapter; 049 050 import ucar.unidata.data.DataCategory; 051 import ucar.unidata.data.DataChoice; 052 import ucar.unidata.data.DataSelection; 053 import ucar.unidata.data.DataSelectionComponent; 054 import ucar.unidata.data.DataSourceDescriptor; 055 import ucar.unidata.data.DataSourceImpl; 056 import ucar.unidata.data.DirectDataChoice; 057 import ucar.unidata.util.Misc; 058 import ucar.unidata.util.WrapperException; 059 060 public class HRITDataSource extends DataSourceImpl { 061 062 /** List of sources files */ 063 protected List sources; 064 065 public static String request; 066 067 /** List of sources files */ 068 protected List adapters; 069 070 private List categories; 071 072 /** for unpersistence */ 073 protected String oldSourceFromBundles; 074 075 private static final String DATA_DESCRIPTION = "HRIT Data"; 076 077 private static int counter = 1; 078 079 /** children choices */ 080 private List myDataChoices = new ArrayList(); 081 082 /** 083 * Default constructor 084 */ 085 public HRITDataSource() {} 086 087 /** 088 * Construct a new HRIT data source. 089 * @param descriptor descriptor for this <code>DataSource</code> 090 * @param fileName name of the HRIT segment file to read 091 * @param properties hashtable of properties 092 * 093 * @throws VisADException problem creating data 094 */ 095 public HRITDataSource(DataSourceDescriptor descriptor, 096 String fileName, Hashtable properties) 097 throws VisADException { 098 this(descriptor, Misc.newList(fileName), properties); 099 } 100 101 /** 102 * Construct a new HRIT data source. 103 * @param descriptor descriptor for this <code>DataSource</code> 104 * @param sources List of filenames 105 * @param properties hashtable of properties 106 * 107 * @throws VisADException problem creating data 108 */ 109 public HRITDataSource(DataSourceDescriptor descriptor, 110 List newSources, Hashtable properties) 111 throws VisADException { 112 113 this(descriptor, newSources, DATA_DESCRIPTION, properties); 114 boolean looksOk = false; 115 String dataCategoryStr = "HRIT Data"; 116 if ((newSources != null) && (newSources.size() >= 1)) { 117 String fileNameFullPath = (String) newSources.get(0); 118 if ((fileNameFullPath != null) && (fileNameFullPath.length() >= 58)) { 119 if ((fileNameFullPath.contains("MSG2")) && (fileNameFullPath.endsWith("-__"))) { 120 String channelStr = fileNameFullPath.substring(fileNameFullPath.lastIndexOf("MSG2") + 13, fileNameFullPath.lastIndexOf("MSG2") + 19); 121 String timeStr = fileNameFullPath.substring(fileNameFullPath.lastIndexOf("MSG2") + 33, fileNameFullPath.lastIndexOf("MSG2") + 45); 122 dataCategoryStr = "MSG2 " + channelStr + " " + timeStr; 123 looksOk = true; 124 } 125 } 126 } 127 if (looksOk) { 128 DataCategory.createCategory(dataCategoryStr); 129 categories = DataCategory.parseCategories(dataCategoryStr + ";IMAGE"); 130 } else { 131 throw new VisADException("Not a decompressed MSG HRIT file"); 132 } 133 } 134 135 /** 136 * Create a HRITDataSource 137 * 138 * @param descriptor The datasource descriptor 139 * @param newSources List of files or urls 140 * @param description The long name 141 * @param properties properties 142 * 143 * @throws VisADException couldn't create the data 144 */ 145 public HRITDataSource(DataSourceDescriptor descriptor, List newSources, 146 String description, Hashtable properties) 147 throws VisADException { 148 149 super(descriptor, "HRIT" + counter, "HRIT" + counter, properties); 150 counter++; 151 sources = newSources; 152 } 153 154 155 /** 156 * Can this data source save its data to local disk 157 * 158 * @return can save to local disk 159 */ 160 public boolean canSaveDataToLocalDisk() { 161 return !isFileBased() && (getProperty(PROP_SERVICE_HTTP) != null); 162 } 163 164 165 /** 166 * Are we getting data from a file or from server 167 * 168 * @return is the data from files 169 */ 170 protected boolean isFileBased() { 171 if (sources.size() == 0) { 172 return false; 173 } 174 return (new File(sources.get(0).toString())).exists(); 175 } 176 177 /** 178 * This is called when the CacheManager detects the need ot clear memory. 179 * It is intended to be overwritten by derived classes that are holding cached 180 * data that is not in the normal putCache facilities provided by this class 181 * since that data is actually managed by the CacheManager 182 */ 183 public void clearCachedData() { 184 super.clearCachedData(); 185 } 186 187 /** 188 * Make and insert the <code>DataChoice</code>-s for this 189 * <code>DataSource</code>. 190 */ 191 public void doMakeDataChoices() { 192 DataChoice choice = null; 193 194 for (int i = 0; i < sources.size(); i++) { 195 String fileNameFullPath = (String) sources.get(i); 196 if (fileNameFullPath.contains("MSG2")) { 197 String channelStr = fileNameFullPath.substring(fileNameFullPath.lastIndexOf("MSG2") + 13, fileNameFullPath.lastIndexOf("MSG2") + 19); 198 String timeStr = fileNameFullPath.substring(fileNameFullPath.lastIndexOf("MSG2") + 33, fileNameFullPath.lastIndexOf("MSG2") + 45); 199 String segStr = fileNameFullPath.substring(fileNameFullPath.lastIndexOf("MSG2") + 27, fileNameFullPath.lastIndexOf("MSG2") + 29); 200 try { 201 choice = doMakeDataChoice(0, "MSG2 " + channelStr + " " + timeStr + " SEGMENT " + segStr); 202 } 203 catch (Exception e) { 204 e.printStackTrace(); 205 System.out.println("doMakeDataChoice failed"); 206 } 207 208 if (choice != null) { 209 addDataChoice(choice); 210 } 211 } 212 } 213 214 } 215 216 private DataChoice doMakeDataChoice(int idx, String var) throws Exception { 217 String name = var; 218 Hashtable ht = null; 219 DirectDataChoice ddc = new DirectDataChoice(this, idx, name, name, categories, ht); 220 return ddc; 221 } 222 223 /** 224 * Create, if needed, and return the list of adapters. 225 * Will return null if there are no valid adapters. 226 * 227 * @return List of adapters or null 228 */ 229 protected List getAdapters() { 230 if ((adapters == null) || (adapters.size() == 0)) { 231 try { 232 makeAdapters(sources); 233 } catch (Exception exc) { 234 setInError(true); 235 throw new WrapperException(exc); 236 } 237 } 238 if (adapters.size() == 0) { 239 adapters = null; 240 } 241 return adapters; 242 } 243 244 /** 245 * Make the adapters for the given list of files 246 * 247 * @param files Data files 248 * 249 * @throws Exception When bad things happen 250 */ 251 private void makeAdapters(List files) throws Exception { 252 adapters = new ArrayList(); 253 } 254 255 256 /** 257 * Create the list of times associated with this DataSource. 258 * @return list of times. 259 */ 260 protected List doMakeDateTimes() { 261 List times = new ArrayList(); 262 return times; 263 } 264 265 /** 266 * Get the data for the given DataChoice and selection criteria. 267 * @param dataChoice DataChoice for selection 268 * @param category DataCategory for the DataChoice (not used) 269 * @param resolution resolution criteria 270 * @param requestProperties extra request properties 271 * @return the Data object for the request 272 * 273 * @throws RemoteException couldn't create a remote data object 274 * @throws VisADException couldn't create the data 275 */ 276 protected Data getDataInner(DataChoice dataChoice, DataCategory category, 277 DataSelection dataparams, 278 Hashtable requestProperties) 279 throws VisADException, RemoteException { 280 281 // for now, hardcoded array of band center wave numbers, such that' 282 // the array index is the band number 283 String[] bandCWN = { 284 "N/A", "006", "008", "016", "039", "062", "073", 285 "087", "097", "108", "120", "134", "___" 286 }; 287 288 // XXX TJJ need to determine this from data type and wavelength 289 int bandNum = 1; 290 // default to BRIT calibration, will check if user picked something else 291 int calType = Calibrator.CAL_BRIT; 292 293 String newRes = (String) dataparams.getProperty("magnification"); 294 int magFactor = 1; 295 if (newRes != null) { 296 try { 297 magFactor = Integer.parseInt(newRes); 298 } catch (NumberFormatException nfe) { 299 nfe.printStackTrace(); 300 } 301 } 302 303 // pull out source index 304 String idxStr = dataChoice.getName().substring(dataChoice.getName().length() - 2, dataChoice.getName().length()); 305 306 Data data = null; 307 308 String [] files = new String[1]; 309 // initialize central wave number string 310 String cwnStr = "006"; 311 for (int i = 0; i < sources.size(); i++) { 312 String tmpStr = (String) sources.get(i); 313 cwnStr = tmpStr.substring(tmpStr.lastIndexOf("MSG2") + 16, tmpStr.lastIndexOf("MSG2") + 19); 314 String segStr = tmpStr.substring(tmpStr.lastIndexOf("MSG2") + 27, tmpStr.lastIndexOf("MSG2") + 29); 315 if (segStr.equals(idxStr)) { 316 files[0] = (String) sources.get(i); 317 } 318 } 319 320 // match up central wave number with band number index 321 for (int i = 0; i < bandCWN.length; i++) { 322 if (bandCWN[i].equals(cwnStr)) { 323 bandNum = i; 324 break; 325 } 326 } 327 328 String newCal = (String) dataparams.getProperty("calibration"); 329 // do checks to only allow valid calibrations here 330 if (newCal != null) { 331 if ((bandNum >= 4) && (bandNum <= 11)) { 332 if (newCal.equals("RAD")) { 333 calType = Calibrator.CAL_RAD; 334 } 335 if (newCal.equals("TEMP")) { 336 calType = Calibrator.CAL_TEMP; 337 } 338 if (newCal.equals("BRIT")) { 339 calType = Calibrator.CAL_BRIT; 340 } 341 } else { 342 if (newCal.equals("RAD")) { 343 calType = Calibrator.CAL_RAD; 344 } 345 if (newCal.equals("ALB")) { 346 calType = Calibrator.CAL_ALB; 347 } 348 if (newCal.equals("BRIT")) { 349 calType = Calibrator.CAL_BRIT; 350 } 351 } 352 } 353 354 HRITAdapter ha; 355 try { 356 ha = new HRITAdapter(files, magFactor, calType, bandNum); 357 data = ha.getData(); 358 } catch (IOException e) { 359 e.printStackTrace(); 360 } 361 362 return data; 363 } 364 365 protected void initDataSelectionComponents( 366 List<DataSelectionComponent> components, 367 final DataChoice dataChoice) { 368 369 try { 370 components.add(new ResolutionSelection(dataChoice)); 371 } 372 catch (Exception e) { 373 e.printStackTrace(); 374 } 375 } 376 377 378 class ResolutionSelection extends DataSelectionComponent { 379 380 DataChoice dataChoice; 381 JPanel display; 382 JComboBox jcbMag = null; 383 JComboBox jcbCal = null; 384 385 ResolutionSelection(DataChoice dataChoice) throws Exception { 386 super("Magnification and Calibration"); 387 this.dataChoice = dataChoice; 388 List names = dataChoice.getCurrentNames(); 389 display = new JPanel(new FlowLayout()); 390 String[] resStrings = { "1", "2", "4", "8", "16" }; 391 jcbMag = new JComboBox(resStrings); 392 display.add(jcbMag); 393 String[] irCalStrings = { "BRIT", "RAD", "RAW", "TEMP" }; 394 String[] visCalStrings = { "BRIT", "RAD", "RAW", "ALB" }; 395 // XXX TJJ - we need a standard mechanism to make this determination 396 // this is a temporary cheap hack: grab the last file name added and 397 // do a hardcoded string match. 398 String sampleFileName = names.get(names.size() - 1).toString(); 399 // those below are considered "visible" bands, yes even IR_016! 400 if ((sampleFileName.contains("VIS")) || 401 (sampleFileName.contains("HRV")) || 402 (sampleFileName.contains("IR_016")) 403 ) { 404 jcbCal = new JComboBox(visCalStrings); 405 } else { 406 jcbCal = new JComboBox(irCalStrings); 407 } 408 display.add(jcbCal); 409 } 410 411 protected JComponent doMakeContents() { 412 try { 413 JPanel panel = new JPanel(new BorderLayout()); 414 panel.add("Center", display); 415 return panel; 416 } 417 catch (Exception e) { 418 System.out.println(e); 419 } 420 return null; 421 } 422 423 public void applyToDataSelection(DataSelection dataSelection) { 424 try { 425 dataSelection.putProperty("magnification", jcbMag.getSelectedItem()); 426 dataSelection.putProperty("calibration", jcbCal.getSelectedItem()); 427 } catch (Exception e) { 428 e.printStackTrace(); 429 } 430 } 431 } 432 }