001 /* 002 * $Id: StormAODTUtil.java,v 1.1 2012/01/04 20:39:38 tommyj 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.control.cyclone; 032 033 import java.util.ArrayList; 034 import java.util.List; 035 036 /** 037 * Created by IntelliJ IDEA. User: yuanho Date: Mar 9, 2009 Time: 2:16:30 PM To 038 * change this template use File | Settings | File Templates. 039 */ 040 public class StormAODTUtil { 041 042 /** 043 * _more_ 044 * 045 * @param odtcurrent 046 * _more_ 047 * @param domain 048 * _more_ 049 * 050 * @return _more_ 051 */ 052 public static List aodtv72_textscreenoutput( 053 StormAODTInfo.IRData odtcurrent, int domain) 054 /* 055 * Output information to text screen. Inputs : global structure 056 * odtcurrent_v72 containting current image information Outputs : none 057 */ 058 { 059 060 int day, mon, year, ibasin, iok; 061 int degree, minute, second, xr8 = 0, xr9 = 0, xrpd = 0; 062 int cloudcat, eyecat, cfft; 063 int ptr, ptr2, nptr; 064 String cdate, ctime, clat, clon; 065 String cmin, csec, clatmax, clonmax; 066 char iout2; 067 String latc = "N", lonc = "W"; 068 String[] cr9 = { "OFF ", "ON ", "WEAKEN" }; 069 String[] crpd = { "OFF ", "FLAG ", "ON ", "ON " }; 070 String[] cbd = { "LOW CLD", "OFF WHT", "DK GRAY", "MD GRAY", "LT GRAY", 071 "BLACK ", "WHITE " }; 072 String[] cr8 = { "NO LIMIT ", "0.5T/6hr ", "1.2T/6hr ", "1.7T/12hr", 073 "2.2T/18hr", "2.7T/24hr", " ", " ", 074 "0.1T/hour", "0.5T/hour", "NO LIMIT ", "0.5T/6hr ", 075 "1.7T/6hr ", "2.2T/12hr", "2.7T/18hr", "3.2T/24hr", 076 " ", " ", "0.1T/hour", "0.5T/hour", 077 "NO LIMIT ", "0.5T/6hr ", "0.7T/6hr ", "1.2T/12hr", 078 "1.7T/18hr", "2.2T/24hr", " ", " ", 079 "0.1T/hour", "0.5T/hour" }; 080 String[] basin = { "ATLANTIC ", "WEST PACIFIC", "EAST PACIFIC", 081 "INDIAN " }; 082 String[] cuse = { "MANUAL", "FORECAST INTERPOLATION", 083 "LAPLACIAN ANALYSIS", "WARMEST PIXEL SEARCH", 084 "SPIRAL ANALYSIS", "RING/SPIRAL COMBINATION", 085 "LINEAR EXTRAPOLATION" }; 086 String scenetype; 087 String scenetypemax; 088 String scenetypemaxll; 089 String eyermw; 090 String version; 091 float pwip, pwiw, cloudtemp, arcd, arcdmax, sdist, xlat, xlon, m; 092 boolean bettercb = false, rmwflag = false; 093 094 /* convert Julian date/time to day/month/year format */ 095 int[] out = aodtv72_yddmy(odtcurrent.date); 096 day = out[0]; 097 mon = out[1]; 098 year = out[2]; 099 /* format character string for date output */ 100 cdate = Integer.toString(day) + "-" + Integer.toString(mon) + "-" 101 + Integer.toString(year); 102 103 /* format character string for time output */ 104 105 ctime = Integer.toString(odtcurrent.time); 106 107 /* convert xx.xxxx latitude format to degree/minute/second format */ 108 xlat = odtcurrent.latitude; 109 xlon = odtcurrent.longitude; 110 out = aodtv72_lldms(xlat); 111 degree = out[0]; 112 minute = out[1]; 113 second = out[2]; 114 115 if (xlat < 0.0) { 116 latc = "S"; 117 } 118 /* format character string for latitude output */ 119 120 clat = Integer.toString(degree) + "-" + Integer.toString(minute) + "-" 121 + Integer.toString(second) + latc; 122 123 /* convert xx.xxxx longitude format to degree/minute/second format */ 124 out = aodtv72_lldms(xlon); 125 degree = out[0]; 126 minute = out[1]; 127 second = out[2]; 128 if (xlon < 0.0) { 129 lonc = "E"; 130 } 131 /* format character string for longitude output */ 132 133 clon = Integer.toString(degree) + "-" + Integer.toString(minute) + "-" 134 + Integer.toString(second) + lonc; 135 136 /* determine current ocean basin in which storm is located */ 137 // ibasin=aodtv72_oceanbasin(xlat,xlon); 138 139 /* determine Dvorak pressure/wind speed in relation to final CI # */ 140 pwip = aodtv72_getpwval(0, odtcurrent.CI, domain); 141 pwiw = aodtv72_getpwval(1, odtcurrent.CI, domain); 142 143 /* determine Rule 8 and Rule 9 screen output values */ 144 xr8 = odtcurrent.rule8; 145 if (odtcurrent.rule9 == 1) { 146 xr9 = 1; 147 } 148 xrpd = odtcurrent.rapiddiss; 149 cloudtemp = odtcurrent.cloudt; 150 /* determine scenetype to be output to screen */ 151 eyecat = odtcurrent.eyescene; 152 cloudcat = odtcurrent.cloudscene; 153 cfft = odtcurrent.cloudfft; 154 if (cloudcat == 2) { 155 scenetype = StormAODTInfo.cloudtype_v72[cloudcat]; 156 } else if (cloudcat == 3) { 157 arcd = (float) (odtcurrent.ringcbval - 1) / 24.0f; 158 arcdmax = (float) (odtcurrent.ringcbvalmax - 1) / 25.0f; 159 if (arcdmax > arcd) { 160 bettercb = true; 161 } 162 scenetype = "CURVED BAND with " + arcd + " ARC in " 163 + cbd[odtcurrent.ringcb]; 164 165 if (bettercb) { 166 scenetypemax = "Maximum CURVED BAND with " + arcdmax 167 + " ARC in " + cbd[odtcurrent.ringcb]; 168 169 /* 170 * convert xx.xxxx latitude format to degree/minute/second 171 * format 172 */ 173 out = aodtv72_lldms(odtcurrent.ringcblatmax); 174 degree = out[0]; 175 minute = out[1]; 176 second = out[2]; 177 178 if (odtcurrent.ringcblatmax < 0.0) { 179 latc = "S"; 180 } 181 /* format character string for latitude output */ 182 clatmax = Integer.toString(degree) + "-" 183 + Integer.toString(minute) + "-" 184 + Integer.toString(second) + latc; 185 186 /* 187 * convert xx.xxxx longitude format to degree/minute/second 188 * format 189 */ 190 out = aodtv72_lldms(odtcurrent.ringcblonmax); 191 degree = out[0]; 192 minute = out[1]; 193 second = out[2]; 194 195 if (odtcurrent.ringcblonmax < 0.0) { 196 lonc = "E"; 197 } 198 /* format character string for longitude output */ 199 clonmax = Integer.toString(degree) + "-" 200 + Integer.toString(minute) + "-" 201 + Integer.toString(second) + lonc; 202 203 scenetypemaxll = " at Lat:" + clatmax + " Lon:" + clonmax; 204 205 } 206 } else if (cloudcat == 4) { 207 sdist = odtcurrent.eyecdosize / 110.0f; 208 if (sdist < 1.30) { 209 scenetype = "SHEAR (%4.2f^ TO DG)* " + sdist; 210 } else { 211 scenetype = "SHEAR (>1.25^ TO DG)*"; 212 } 213 214 } else { 215 if (eyecat <= 2) { 216 scenetype = StormAODTInfo.eyetype_v72[eyecat]; 217 if (eyecat <= 2) { 218 rmwflag = true; 219 } 220 221 if (odtcurrent.rmw < 0.0) { 222 if (eyecat == 1) { 223 eyermw = "<10"; 224 } else { 225 eyermw = "N/A"; 226 } 227 } else { 228 eyermw = Integer.toString((int) odtcurrent.rmw); 229 /* if(eyecat==1) sprintf(eyermw,"<10"); */ 230 } 231 } else { 232 scenetype = "CLOUD REGION* " 233 + StormAODTInfo.cloudtype_v72[cloudcat]; 234 } 235 236 } 237 238 List result = new ArrayList(); 239 240 /* send results to the screen */ 241 result.add("<tr><td>" 242 + "\n****************************************************\n" 243 + "</td></tr>"); 244 result.add("<tr><td>" + " ADVANCED DVORAK TECHNIQUE \n" 245 + "</td></tr>"); 246 result.add("<tr><td>" 247 + " Tropical Cyclone Intensity Algorithm \n\n" 248 + "</td></tr>"); 249 result.add("<tr><td>" + " ----- Current Analysis ----- \n" 250 + "</td></tr>"); 251 result.add("<tr><td>" + " Date : " + cdate + "Time : " + ctime + "\n" 252 + "</td></tr>"); 253 result.add("<tr><td>" + " Lat : " + clat + "Lon : " + clon + "\n" 254 + "</td></tr>"); 255 if ((odtcurrent.land == 1)) { 256 result.add("<tr><td>" 257 + " TROPICAL CYCLONE OVER LAND\n" 258 + "</td></tr>"); 259 result.add("<tr><td>" 260 + " NO ADT ANALYSIS AVAILABLE\n" 261 + "</td></tr>"); 262 } else { 263 result.add("<tr><td>" + " CI# /Pressure/ Vmax\n" + "</td></tr>"); 264 result.add("<tr><td>" + odtcurrent.CI + " " 265 + (pwip + odtcurrent.CIadjp) + " " + pwiw + "\n" 266 + "</td></tr>"); 267 268 result.add("<tr><td>" + "Latitude bias adjustment to MSLP : " 269 + odtcurrent.CIadjp + "\n" + "</td></tr>"); 270 result.add("<tr><td>" + " Center Temp : " + odtcurrent.eyet 271 + "Cloud Region Temp : " + cloudtemp + "\n" + "</td></tr>"); 272 result.add("<tr><td>" + " Scene Type : " + scenetype + "\n" 273 + "</td></tr>"); 274 275 } 276 277 result.add("<tr><td>" 278 + "\n****************************************************\n" 279 + "</td></tr>"); 280 281 return result; 282 283 } 284 285 /** 286 * _more_ 287 * 288 * @param llval 289 * _more_ 290 * 291 * @return _more_ 292 */ 293 public static int[] aodtv72_lldms(float llval) 294 /* 295 * Convert degree.degree to degree/minute/second format. Inputs : llval - 296 * latitude/longitude to convert Outputs : degree - degrees minute - minutes 297 * second - seconds 298 */ 299 { 300 int deg; 301 float min, sec; 302 303 deg = (int) llval; 304 min = (llval - (float) deg) * 60.0f; 305 sec = (min - (float) ((int) min)) * 60.0f; 306 307 int[] out = { deg, (int) min, (int) sec }; 308 309 return out; 310 } 311 312 /** 313 * _more_ 314 * 315 * @param syd 316 * _more_ 317 * 318 * @return _more_ 319 */ 320 public static int[] aodtv72_yddmy(int syd) 321 /* 322 * Convert yyyyddd to dd/mm/yy format. Inputs : syd - Julian day (yyyyddd) 323 * Outputs : day - date month - month year - year (yyyy) 324 */ 325 { 326 int[][] dn = { 327 { 0, 31, 59, 90, 120, 151, 181, 212, 243, 273, 304, 334, 365 }, 328 { 0, 31, 60, 91, 121, 152, 182, 213, 244, 274, 305, 335, 366 } }; 329 int iyy, idd, imm, ily = 0; 330 331 iyy = syd / 1000; 332 if (iyy < 1900) { 333 if (iyy > 70) { 334 iyy = iyy + 1900; 335 } else { 336 iyy = iyy + 2000; 337 } 338 } 339 idd = (syd % 1000); 340 if ((iyy % 4) == 0) { 341 ily = 1; 342 } 343 for (imm = 0; imm < 13; imm++) { 344 if (idd <= dn[ily][imm]) { 345 break; 346 } 347 } 348 349 int[] out = { idd - dn[ily][imm - 1], imm, iyy }; 350 return out; 351 352 } 353 354 /** 355 * _more_ 356 * 357 * @param ival 358 * _more_ 359 * @param cival 360 * _more_ 361 * @param idomain_v72 362 * _more_ 363 * 364 * @return _more_ 365 */ 366 public static float aodtv72_getpwval(int ival, float cival, int idomain_v72) 367 /* 368 * Obtain pressure or wind_v72 value (for Atlantic or West Pacific storms) 369 * given the intensity estimate value. Inputs : ival - flag for wind_v72 (1) 370 * or pressure (0) output cival - Current Intensity (CI) value Outputs : 371 * return value is pressure/wind_v72 value 372 */ 373 { 374 float value; 375 int ixx = 2; 376 377 /* determine correct pressure/wind_v72 array bin */ 378 while ((cival > StormAODTInfo.tno_v72[ixx]) && (ixx < 82)) { 379 ixx++; 380 } 381 382 /* convert CI value to wind_v72/pressure value */ 383 if (ival == 1) { 384 value = (float) StormAODTInfo.wind_v72[ixx]; /* WIND */ 385 } else { 386 value = (float) StormAODTInfo.pres_v72[idomain_v72][ixx]; /* PRESSURE */ 387 } 388 389 return value; 390 } 391 392 }