001/* 002 * This file is part of McIDAS-V 003 * 004 * Copyright 2007-2016 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 029package edu.wisc.ssec.mcidasv.data.hrit; 030 031import java.awt.BorderLayout; 032import java.awt.FlowLayout; 033import java.io.File; 034import java.io.IOException; 035import java.rmi.RemoteException; 036import java.util.ArrayList; 037import java.util.Hashtable; 038import java.util.List; 039 040import javax.swing.JComboBox; 041import javax.swing.JComponent; 042import javax.swing.JPanel; 043 044import edu.wisc.ssec.mcidas.Calibrator; 045 046import visad.Data; 047import visad.VisADException; 048import visad.data.hrit.HRITAdapter; 049 050import ucar.unidata.data.DataCategory; 051import ucar.unidata.data.DataChoice; 052import ucar.unidata.data.DataSelection; 053import ucar.unidata.data.DataSelectionComponent; 054import ucar.unidata.data.DataSourceDescriptor; 055import ucar.unidata.data.DataSourceImpl; 056import ucar.unidata.data.DirectDataChoice; 057import ucar.unidata.util.Misc; 058import ucar.unidata.util.WrapperException; 059 060public 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} 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} 104 * @param newSources 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 {@link DataChoice DataChoices} for this {@code DataSource}. 189 */ 190 public void doMakeDataChoices() { 191 DataChoice choice = null; 192 193 for (int i = 0; i < sources.size(); i++) { 194 String fileNameFullPath = (String) sources.get(i); 195 if (fileNameFullPath.contains("MSG2")) { 196 String channelStr = fileNameFullPath.substring(fileNameFullPath.lastIndexOf("MSG2") + 13, fileNameFullPath.lastIndexOf("MSG2") + 19); 197 String timeStr = fileNameFullPath.substring(fileNameFullPath.lastIndexOf("MSG2") + 33, fileNameFullPath.lastIndexOf("MSG2") + 45); 198 String segStr = fileNameFullPath.substring(fileNameFullPath.lastIndexOf("MSG2") + 27, fileNameFullPath.lastIndexOf("MSG2") + 29); 199 try { 200 choice = doMakeDataChoice(0, "MSG2 " + channelStr + " " + timeStr + " SEGMENT " + segStr); 201 } 202 catch (Exception e) { 203 e.printStackTrace(); 204 System.out.println("doMakeDataChoice failed"); 205 } 206 207 if (choice != null) { 208 addDataChoice(choice); 209 } 210 } 211 } 212 213 } 214 215 private DataChoice doMakeDataChoice(int idx, String var) throws Exception { 216 String name = var; 217 Hashtable ht = null; 218 DirectDataChoice ddc = new DirectDataChoice(this, idx, name, name, categories, ht); 219 return ddc; 220 } 221 222 /** 223 * Create, if needed, and return the list of adapters. 224 * Will return null if there are no valid adapters. 225 * 226 * @return List of adapters or null 227 */ 228 protected List getAdapters() { 229 if ((adapters == null) || (adapters.size() == 0)) { 230 try { 231 makeAdapters(sources); 232 } catch (Exception exc) { 233 setInError(true); 234 throw new WrapperException(exc); 235 } 236 } 237 if (adapters.size() == 0) { 238 adapters = null; 239 } 240 return adapters; 241 } 242 243 /** 244 * Make the adapters for the given list of files 245 * 246 * @param files Data files 247 * 248 * @throws Exception When bad things happen 249 */ 250 private void makeAdapters(List files) throws Exception { 251 adapters = new ArrayList(); 252 } 253 254 255 /** 256 * Create the list of times associated with this DataSource. 257 * @return list of times. 258 */ 259 protected List doMakeDateTimes() { 260 List times = new ArrayList(); 261 return times; 262 } 263 264 /** 265 * Get the data for the given DataChoice and selection criteria. 266 * @param dataChoice DataChoice for selection 267 * @param category DataCategory for the DataChoice (not used) 268 * @param dataparams Resolution criteria. 269 * @param requestProperties extra request properties 270 * @return the Data object for the request 271 * 272 * @throws RemoteException couldn't create a remote data object 273 * @throws VisADException couldn't create the data 274 */ 275 protected Data getDataInner(DataChoice dataChoice, DataCategory category, 276 DataSelection dataparams, 277 Hashtable requestProperties) 278 throws VisADException, RemoteException { 279 280 // for now, hardcoded array of band center wave numbers, such that' 281 // the array index is the band number 282 String[] bandCWN = { 283 "N/A", "006", "008", "016", "039", "062", "073", 284 "087", "097", "108", "120", "134", "___" 285 }; 286 287 // XXX TJJ need to determine this from data type and wavelength 288 int bandNum = 1; 289 // default to BRIT calibration, will check if user picked something else 290 int calType = Calibrator.CAL_BRIT; 291 292 String newRes = (String) dataparams.getProperty("magnification"); 293 int magFactor = 1; 294 if (newRes != null) { 295 try { 296 magFactor = Integer.parseInt(newRes); 297 } catch (NumberFormatException nfe) { 298 nfe.printStackTrace(); 299 } 300 } 301 302 // pull out source index 303 String idxStr = dataChoice.getName().substring(dataChoice.getName().length() - 2, dataChoice.getName().length()); 304 305 Data data = null; 306 307 String [] files = new String[1]; 308 // initialize central wave number string 309 String cwnStr = "006"; 310 for (int i = 0; i < sources.size(); i++) { 311 String tmpStr = (String) sources.get(i); 312 cwnStr = tmpStr.substring(tmpStr.lastIndexOf("MSG2") + 16, tmpStr.lastIndexOf("MSG2") + 19); 313 String segStr = tmpStr.substring(tmpStr.lastIndexOf("MSG2") + 27, tmpStr.lastIndexOf("MSG2") + 29); 314 if (segStr.equals(idxStr)) { 315 files[0] = (String) sources.get(i); 316 } 317 } 318 319 // match up central wave number with band number index 320 for (int i = 0; i < bandCWN.length; i++) { 321 if (bandCWN[i].equals(cwnStr)) { 322 bandNum = i; 323 break; 324 } 325 } 326 327 String newCal = (String) dataparams.getProperty("calibration"); 328 // do checks to only allow valid calibrations here 329 if (newCal != null) { 330 if ((bandNum >= 4) && (bandNum <= 11)) { 331 if (newCal.equals("RAD")) { 332 calType = Calibrator.CAL_RAD; 333 } 334 if (newCal.equals("TEMP")) { 335 calType = Calibrator.CAL_TEMP; 336 } 337 if (newCal.equals("BRIT")) { 338 calType = Calibrator.CAL_BRIT; 339 } 340 } else { 341 if (newCal.equals("RAD")) { 342 calType = Calibrator.CAL_RAD; 343 } 344 if (newCal.equals("ALB")) { 345 calType = Calibrator.CAL_ALB; 346 } 347 if (newCal.equals("BRIT")) { 348 calType = Calibrator.CAL_BRIT; 349 } 350 } 351 } 352 353 HRITAdapter ha; 354 try { 355 ha = new HRITAdapter(files, magFactor, calType, bandNum); 356 data = ha.getData(); 357 } catch (IOException e) { 358 e.printStackTrace(); 359 } 360 361 return data; 362 } 363 364 protected void initDataSelectionComponents( 365 List<DataSelectionComponent> components, 366 final DataChoice dataChoice) { 367 368 try { 369 components.add(new ResolutionSelection(dataChoice)); 370 } 371 catch (Exception e) { 372 e.printStackTrace(); 373 } 374 } 375 376 377 class ResolutionSelection extends DataSelectionComponent { 378 379 DataChoice dataChoice; 380 JPanel display; 381 JComboBox jcbMag = null; 382 JComboBox jcbCal = null; 383 384 ResolutionSelection(DataChoice dataChoice) throws Exception { 385 super("Magnification and Calibration"); 386 this.dataChoice = dataChoice; 387 List names = dataChoice.getCurrentNames(); 388 display = new JPanel(new FlowLayout()); 389 String[] resStrings = { "1", "2", "4", "8", "16" }; 390 jcbMag = new JComboBox(resStrings); 391 display.add(jcbMag); 392 String[] irCalStrings = { "BRIT", "RAD", "RAW", "TEMP" }; 393 String[] visCalStrings = { "BRIT", "RAD", "RAW", "ALB" }; 394 // XXX TJJ - we need a standard mechanism to make this determination 395 // this is a temporary cheap hack: grab the last file name added and 396 // do a hardcoded string match. 397 String sampleFileName = names.get(names.size() - 1).toString(); 398 // those below are considered "visible" bands, yes even IR_016! 399 if ((sampleFileName.contains("VIS")) || 400 (sampleFileName.contains("HRV")) || 401 (sampleFileName.contains("IR_016")) 402 ) { 403 jcbCal = new JComboBox(visCalStrings); 404 } else { 405 jcbCal = new JComboBox(irCalStrings); 406 } 407 display.add(jcbCal); 408 } 409 410 protected JComponent doMakeContents() { 411 try { 412 JPanel panel = new JPanel(new BorderLayout()); 413 panel.add("Center", display); 414 return panel; 415 } 416 catch (Exception e) { 417 System.out.println(e); 418 } 419 return null; 420 } 421 422 public void applyToDataSelection(DataSelection dataSelection) { 423 try { 424 dataSelection.putProperty("magnification", jcbMag.getSelectedItem()); 425 dataSelection.putProperty("calibration", jcbCal.getSelectedItem()); 426 } catch (Exception e) { 427 e.printStackTrace(); 428 } 429 } 430 } 431}