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