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 }