001/* 002 * This file is part of McIDAS-V 003 * 004 * Copyright 2007-2025 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 https://www.gnu.org/licenses/. 027 */ 028 029package edu.wisc.ssec.mcidasv.data; 030 031import edu.wisc.ssec.mcidas.AREAnav; 032import edu.wisc.ssec.mcidas.McIDASUtil; 033 034import java.io.*; 035import java.util.Date; 036 037/** 038 * Class FrameDirectory holds information obtained 039 * from frame directory files, FRAMEn.p, from McIdas-X 040 */ 041public 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}