001 /*
002 * $Id: HRITDataSource.java,v 1.11 2012/02/19 17:35:40 davep 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.hrit;
032
033 import java.awt.BorderLayout;
034 import java.awt.FlowLayout;
035 import java.io.File;
036 import java.io.IOException;
037 import java.rmi.RemoteException;
038 import java.util.ArrayList;
039 import java.util.Hashtable;
040 import java.util.List;
041
042 import javax.swing.JComboBox;
043 import javax.swing.JComponent;
044 import javax.swing.JPanel;
045
046 import edu.wisc.ssec.mcidas.Calibrator;
047
048 import visad.Data;
049 import visad.VisADException;
050 import visad.data.hrit.HRITAdapter;
051
052 import ucar.unidata.data.DataCategory;
053 import ucar.unidata.data.DataChoice;
054 import ucar.unidata.data.DataSelection;
055 import ucar.unidata.data.DataSelectionComponent;
056 import ucar.unidata.data.DataSourceDescriptor;
057 import ucar.unidata.data.DataSourceImpl;
058 import ucar.unidata.data.DirectDataChoice;
059 import ucar.unidata.util.Misc;
060 import ucar.unidata.util.WrapperException;
061
062 public 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 }