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;
030
031 import edu.wisc.ssec.mcidas.AREAnav;
032 import edu.wisc.ssec.mcidas.McIDASUtil;
033
034 import java.io.*;
035 import java.util.Date;
036
037 /**
038 * Class FrameDirectory holds information obtained
039 * from frame directory files, FRAMEn.p, from McIdas-X
040 */
041 public class FrameDirectory {
042
043 /** time of data in frame */
044 private Date nominalTime;
045
046 /** Sensor source name */
047 private String sensorName;
048
049 /** Sensor source number */
050 private int sensorNumber;
051
052 /** Year and Julian day, ccyyddd */
053 private int cyd;
054
055 /** Time, hhmmss */
056 private int hms;
057
058 /** Band number */
059 private int band;
060
061 /** Upper-left corner satellite coordinates */
062 private int uLLine;
063 private int uLEle;
064
065 /** Magnification factors */
066 private int lineMag;
067 private int eleMag;
068
069 /** Resolution factors */
070 private int lineRes;
071 private int eleRes;
072
073 /** Navigation block */
074 private int[] nav;
075
076 /** Navigation block */
077 private int[] aux;
078
079 /** GRAF navigation type */
080 private int AREAnavGRAF = 1196572998;
081
082 /**
083 * Constructor
084 */
085 public FrameDirectory() { }
086
087 /**
088 * Copy constructor
089 *
090 * @param that The FrameDirectory to copy
091 *
092 */
093 public FrameDirectory(FrameDirectory that) {
094 this.sensorName = that.sensorName;
095 this.sensorNumber = that.sensorNumber;
096 this.cyd = that.cyd;
097 this.hms = that.hms;
098 this.nominalTime = new Date(1000*McIDASUtil.mcDayTimeToSecs(that.cyd,that.hms));
099 this.band = that.band;
100 this.uLLine = that.uLLine;
101 this.uLEle = that.uLEle;
102 this.lineMag = that.lineMag;
103 this.eleMag = that.eleMag;
104 this.lineRes = that.lineRes;
105 this.eleRes = that.eleRes;
106 this.nav = that.nav;
107 this.aux = that.aux;
108 }
109
110 /**
111 * Constructor
112 *
113 * @param directory frame directory from McIdax-X
114 *
115 */
116 public FrameDirectory(int[] directory) {
117 //System.out.println("FrameDirectory constructor:");
118 this.sensorNumber = directory[0];
119 // if (this.sensorNumber != -1)
120 // this.sensorName = getName(directory[0]);
121 // else
122 // this.sensorName = "";
123 this.sensorName = "";
124 this.cyd = directory[1];
125 this.hms = directory[2];
126 this.nominalTime = new Date(1000*McIDASUtil.mcDayTimeToSecs(cyd,hms));
127 this.band = directory[3];
128 this.uLLine = directory[4];
129 this.uLEle = directory[5];
130 this.lineRes = directory[10];
131 this.eleRes = directory[11];
132 this.lineMag = directory[19];
133 this.eleMag = directory[20];
134
135 // if (this.lineMag < 0) this.lineMag = 1;
136 // if (this.eleMag < 0) this.eleMag = 1;
137 // this.lineMag=1;
138 // this.eleMag=1;
139
140 /*
141 System.out.println(" cyd=" + cyd);
142 System.out.println(" hms=" + hms);
143 System.out.println(" band=" + band);
144 System.out.println(" uLLine=" + uLLine);
145 System.out.println(" uLEle=" + uLEle);
146 System.out.println(" lineMag=" + lineMag);
147 System.out.println(" eleMag=" + eleMag);
148 System.out.println(" lineRes=" + lineRes);
149 System.out.println(" eleRes=" + eleRes);
150 */
151 // System.out.println("Navigation type " + directory[64] + ": " + navIntToString(directory[64]));
152
153 int navLength;
154 if (directory[64] == AREAnav.LALO) navLength = 128;
155 else navLength = 640;
156 this.nav = new int[navLength];
157 System.arraycopy(directory, 64, this.nav, 0, navLength);
158
159 if (this.nav[0] == this.AREAnavGRAF)
160 this.nav = transformGRAFIntoRECT(this.nav);
161
162 int auxLength = 0;
163 int rows = 0;
164 int cols = 0;
165 int begLat = 0;
166 int begLon = 0;
167 if (this.nav[0] == AREAnav.LALO) {
168 rows = this.nav[65];
169 cols = this.nav[66];
170 begLat = this.nav[78]/4;
171 begLon = this.nav[79]/4;
172 auxLength = begLon + (rows*cols);
173 this.aux = new int[auxLength];
174 }
175 else {
176 this.aux = new int[1];
177 }
178 int numPoints = rows * cols;
179 System.arraycopy(directory, 64+navLength, this.aux, begLat, numPoints);
180 if (auxLength > 0) {
181 System.arraycopy(directory, 64+navLength+numPoints, this.aux, begLon, numPoints);
182 }
183 // System.out.println("FrameDirectory navLength: " + navLength + ", auxLength: " + auxLength);
184 }
185
186 /*
187 * TODO: FrameDirectory.getName() is not used right now... keep the code here just in case.
188 * If you do decide you need it, read SATANNOT over the bridge, not locally...
189 */
190 /*
191 public String getName(int num) {
192 String name = "";
193 FileInputStream fis;
194 //byte[] bline={0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0};
195 byte[] bline = new byte[31];
196 int off=0;
197 int ret = 0;
198 int sensor=0;
199
200 System.out.println("Fix this: SATANNOT should not be read locally");
201 try {
202 fis = new FileInputStream("/home/mcidas/data/SATANNOT");
203 } catch(Exception e) {
204 System.out.println("FrameDirectory: Can't find SATANNOT");
205 return name;
206 }
207 int counter=0;
208 int sensor1=0;
209 int sensor2=0;
210 int sensor3=0;
211 while (ret != -1) {
212 try {
213 int ptr=0;
214 int next=0;
215 for (int i=0;i<19; i++) {
216 next = fis.read();
217 bline[ptr] = (byte)next;
218 ptr++;
219 }
220 name = new String(bline, 0, ptr);
221 for (int i=20;i<30; i++) {
222 off = fis.read();
223 }
224 sensor1 = fis.read()-48;
225 sensor2 = fis.read()-48;
226 sensor3 = fis.read()-48;
227 sensor = 0;
228 if (sensor1 >= 0) {
229 sensor = sensor1;
230 }
231 if (sensor2 >= 0) {
232 sensor *= 10;
233 sensor += sensor2;
234 }
235 if (sensor3 >= 0) {
236 sensor *= 10;
237 sensor += sensor3;
238 }
239 for (int i=32; i<80; i++)
240 off = fis.read();
241 } catch(Exception e) {
242 System.out.println("FrameDirectory: Can't read SATANNOT");
243 try {
244 fis.close();
245 } catch (Exception ee) {
246 }
247 return name;
248 }
249 if (sensor == num) ret =-1;
250 counter++;
251 if (counter>200) ret=-1;
252 }
253 try {
254 fis.close();
255 } catch (Exception e) {
256 }
257 return name;
258 }
259 */
260
261 /**
262 * Get the nominalTime.
263 *
264 * @return The nominalTime.
265 */
266 public Date getNominalTime() {
267 return this.nominalTime;
268 }
269
270 /**
271 * Get the sensorName.
272 *
273 * @return The sensorName.
274 */
275 public String getSensorName() {
276 return this.sensorName;
277 }
278
279 /**
280 * Get the sensorNumber.
281 *
282 * @return The sensorNumber.
283 */
284 public int getSensorNumber() {
285 return this.sensorNumber;
286 }
287
288 /**
289 * Get cyd.
290 *
291 * @return cyd.
292 */
293 public int getCyd() {
294 return this.cyd;
295 }
296
297 /**
298 * Get hms.
299 *
300 * @return hms.
301 */
302 public int getHms() {
303 return this.hms;
304 }
305
306 /**
307 * Get band.
308 *
309 * @return band.
310 */
311 public int getBand() {
312 return this.band;
313 }
314
315 /**
316 * Set sensorName.
317 *
318 * @param newName The new vaue for sensorName.
319 */
320 public void setSensorName(String newName) {
321 this.sensorName = newName;
322 }
323
324 /**
325 * Set cyd.
326 *
327 * @param newCyd The new vaue for cyd.
328 */
329 public void setCyd(int newCyd) {
330 this.cyd = newCyd;
331 }
332
333 /**
334 * Set hms.
335 *
336 * @param newHms The new vaue for hms.
337 */
338 public void setHms(int newHms) {
339 this.hms = newHms;
340 }
341
342 /**
343 * Set band.
344 *
345 * @param newBand The new vaue for band.
346 */
347 public void setBand(int newBand) {
348 this.band = newBand;
349 }
350
351 /**
352 * Get a String representation of this object
353 * @return a string representation
354 */
355 public String toString() {
356 StringBuffer buf = new StringBuffer();
357 buf.append(this.sensorName + " ");
358 buf.append(this.sensorNumber + " ");
359 buf.append(this.cyd + " ");
360 buf.append(this.hms + " ");
361 buf.append(this.band);
362 return buf.toString();
363 }
364
365 public int[] getFrameNav() {
366 return nav;
367 }
368
369 public int[] getFrameAux() {
370 return aux;
371 }
372
373 public int getLineRes() {
374 return lineRes;
375 }
376
377 public int getEleRes() {
378 return eleRes;
379 }
380
381 public int getULLine() {
382 return uLLine;
383 }
384
385 public int getULEle() {
386 return uLEle;
387 }
388
389 /**
390 * Print the nav type
391 */
392 private String navIntToString(int navInt) {
393 int int1 = navInt/0x1000000&0xff;
394 int int2 = navInt/0x10000&0xff;
395 int int3 = navInt/0x100&0xff;
396 int int4 = navInt&0xff;
397 String char1 = new Character((char)int1).toString();
398 String char2 = new Character((char)int2).toString();
399 String char3 = new Character((char)int3).toString();
400 String char4 = new Character((char)int4).toString();
401 String returnString = char1 + char2 + char3 + char4;
402 return returnString;
403 }
404
405 /**
406 * Since GRAF is not a real data projection, try to munge it into RECT for VisAD
407 */
408 private int[] transformGRAFIntoRECT(int[] nav) {
409 if (nav[0] != this.AREAnavGRAF) return nav;
410 int[] RECT = nav;
411 int minLat = RECT[21];
412 int maxLat = RECT[22];
413 int minLon = RECT[23];
414 int maxLon = RECT[24];
415 int minY = RECT[25];
416 int maxY = RECT[26];
417 int minX = RECT[27];
418 int maxX = RECT[28];
419 int centerLat = Math.round((maxLat - minLat) / 2) + minLat;
420 int centerLon = Math.round((maxLon - minLon) / 2) + minLon;
421 int rangeLat = maxLat - minLat;
422 int rangeLon = maxLon - minLon;
423 int centerY = Math.round((maxY - minY) / 2) + minY;
424 int centerX = Math.round((maxX - minX) / 2) + minX;
425 int rangeY = maxY - minY;
426 int rangeX = maxX - minX;
427 RECT[0] = AREAnav.RECT;
428 RECT[1] = centerY - minY;
429 RECT[2] = centerLat;
430 RECT[3] = centerX - minX;
431 RECT[4] = centerLon;
432 RECT[5] = Math.round(rangeLat / rangeY);
433 RECT[6] = Math.round(rangeLon / rangeX);
434 // Earth constants (eccentricity and radius)
435 RECT[7] = 6378388;
436 RECT[8] = 81992;
437 for (int i=9; i<24; i++) RECT[i] = 0;
438 return RECT;
439 }
440 }