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 }