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