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