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